C#asynchronous – 它是如何工作的?
微软今天(2010年10月28日)发布了Visual StudioasynchronousCTP ,将async
和await
关键字引入到C#/ VB中,用于执行asynchronous方法。
首先,我认为编译器将关键字转换为线程的创build,但是根据白皮书和Anders Hejlsberg的PDC演示 (在31:00),asynchronous操作完全在主线程上发生。
我怎么能在同一个线程上并行执行一个操作? 在技术上怎么可能以及在IL中实际翻译的function是什么?
它与C#2.0中的yield return
关键字类似。
一个asynchronous方法实际上并不是一个普通的顺序方法。 它被编译成状态机(一个对象),并有一些状态(局部variables被转换成对象的字段)。 两次使用await
之间的每个代码块都是状态机的一个“步骤”。
这意味着当方法启动时,它只是运行第一步,然后状态机返回并安排一些工作 – 工作完成后,它将运行状态机的下一步。 例如这个代码:
async Task Demo() { var v1 = foo(); var v2 = await bar(); more(v1, v2); }
会被翻译成类似于:
class _Demo { int _v1, _v2; int _state = 0; Task<int> _await1; public void Step() { switch(this._state) { case 0: this._v1 = foo(); this._await1 = bar(); // When the async operation completes, it will call this method this._state = 1; op.SetContinuation(Step); case 1: this._v2 = this._await1.Result; // Get the result of the operation more(this._v1, this._v2); } }
最重要的部分是它只是使用SetContinuation
方法来指定操作完成时,它应该再次调用Step
方法(并且方法知道它应该使用_state
字段运行原始代码的第二位)。 你可以很容易的想象, SetContinuation
就像btn.Click += Step
,它可以完全在一个线程上运行。
C#中的asynchronous编程模型非常接近F#asynchronous工作stream程(事实上,除了一些技术细节外,本质上是一样的),使用async
编写react native的单线程GUI应用程序是一个相当有趣的领域 – 至less我这样想 – 看看这篇文章 (也许我现在应该写一个C#版本:-))。
该翻译类似于迭代器(和yield return
),实际上,可以使用迭代器在C#中实现asynchronous编程。 我刚才写了一篇关于这个文章的文章 – 我认为它仍然可以让你对翻译的工作有一些了解。
我怎么能在同一个线程上并行执行一个操作?
你不能。 asynchronous不是“并行”或“并发” 。 asynchronous可以用并行来实现,也可以不是。 可以通过将工作分解成小块来实现,将每一块工作放在一个队列中,然后在线程碰巧没有做任何事情时执行每一块工作。
我在博客上有一系列的文章,讲述这些东西是如何工作的。 直接关系到这个问题的人可能会在下周四的星期四上升。 看
http://blogs.msdn.com/b/ericlippert/archive/tags/async/
了解详情。
据我所知, async
和await
关键字的作用是,每当async
方法使用await
关键字时,编译器会将该方法的其余部分转换为在asynchronous操作完成时调度的延续。 这允许async
方法立即返回给调用者,并在asynchronous部分完成时恢复工作。
根据现有的论文,有很多的细节,但是除非我弄错了,否则这就是它的要点。
正如我所看到的,asynchronous方法的目的不是并行运行大量的代码,而是将asynchronous方法切成许多小块,可以根据需要调用。 关键是编译器将使用任务/连续处理所有复杂的callback连线。 这不仅降低了复杂度,而且允许像传统的同步代码一样写或多或less的asynchronous方法。