它的工作原理类似于yield return
C# 2.0 中的关键字。
异步方法实际上并不是普通的顺序方法。它被编译成具有某种状态的状态机(对象)(局部变量被转换为对象的字段)。两次使用之间的每个代码块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# 中的异步编程模型非常接近 F# 异步工作流程(事实上,除了一些技术细节之外,本质上是同一件事),并且使用以下代码编写反应式单线程 GUI 应用程序async
是一个非常有趣的领域 - 至少我这么认为 - 例如参见本文 http://dotnetslackers.com/articles/net/Programming-user-interfaces-using-f-sharp-workflows.aspx(也许我现在应该写一个 C# 版本:-))。
翻译类似于迭代器(和yield return
)而且事实上,很早以前在 C# 中就可以使用迭代器来实现异步编程。我写一篇关于那个的文章 http://tomasp.net/blog/csharp-async.aspx不久前 - 我认为它仍然可以让您了解翻译的工作原理。