83

有人可以确认我是否正确理解了 Async await 关键字吗?(使用 CTP 版本 3)

到目前为止,我已经发现在方法调用之前插入 await 关键字基本上做了两件事,A. 它创建一个立即返回和 B. 它创建一个在异步方法调用完成时调用的“延续”。在任何情况下,延续都是该方法的代码块的剩余部分。

所以我想知道的是,这两段代码在技术上是否等效,如果是,这是否基本上意味着 await 关键字与创建 ContinueWith Lambda 相同(即:它基本上是一个编译器快捷方式)?如果不是,有什么区别?

bool Success =
    await new POP3Connector(
        "mail.server.com", txtUsername.Text, txtPassword.Text).Connect();
// At this point the method will return and following code will
// only be invoked when the operation is complete(?)
MessageBox.Show(Success ? "Logged In" : "Wrong password");

VS

(new POP3Connector(
    "mail.server.com", txtUsername.Text, txtPassword.Text ).Connect())
.ContinueWith((success) =>
    MessageBox.Show(success.Result ? "Logged In" : "Wrong password"));
4

2 回答 2

85

总体思路是正确的——该方法的其余部分被制成某种延续。

快速路径”博客文章详细介绍了async/await编译器转换的工作原理。

差异,在我的脑海中:

await关键字还使用了“调度上下文”概念。调度上下文是SynchronizationContext.Current如果它存在,则回退到TaskScheduler.Current. 然后继续在调度上下文上运行。因此,更接近的近似值是传递TaskScheduler.FromCurrentSynchronizationContextContinueWithTaskScheduler.Current如有必要,可以返回。

实际async/await实现是基于模式匹配的;它使用“等待”模式,允许等待任务以外的其他事情。一些示例是 WinRT 异步 API、一些特殊方法(如YieldRx observables)和不会像 GC 那样严重影响到的特殊套接字等待对象。任务很强大,但它们并不是唯一的等待对象。

我想到了另一个细微的细微差别:如果 awaitable 已经完成,那么该async方法实际上并没有在该点返回;它同步继续。所以它有点像通过TaskContinuationOptions.ExecuteSynchronously,但没有堆栈相关的问题。

于 2012-01-07T04:39:37.443 回答
9

“基本上”是这样,但生成的代码不仅仅如此。有关生成代码的更多详细信息,我强烈推荐 Jon Skeet 的 Eduasync 系列:

http://codeblog.jonskeet.uk/category/eduasync/

特别是,帖子 #7 介绍了生成的内容(从 CTP 2 开始)以及原因,因此可能非常适合您目前正在寻找的内容:

http://codeblog.jonskeet.uk/2011/05/20/eduasync-part-7-generated-code-from-a-simple-async-method/

编辑:我认为它可能比你从问题中寻找的更详细,但是如果你想知道当你在方法中有多个等待时会是什么样子,那在帖子 #9 中有所介绍:)

http://codeblog.jonskeet.uk/2011/05/30/eduasync-part-9-generated-code-for-multiple-awaits/

于 2012-01-07T04:38:52.223 回答