在等待任务返回之前会发生什么?

Cas*_*roy 4 c# asynchronous async-await

我正在尝试新的async和await关键字.我生成了以下异步函数:

private async static Task<string> GetStringAsync(string pageAddress)
{
    HttpClient client = new HttpClient();
    return client.GetStringAsync(pageAddress);
}
Run Code Online (Sandbox Code Playgroud)

我知道我正在返回a Task<String>并且可以等待另一种方法的结果.这种方法很好.我的问题是当我用以下内容替换上面函数的第二行时会发生什么(在引擎盖下)(请注意await关键字的介绍):

return await client.GetStringAsync(pageAddress);
Run Code Online (Sandbox Code Playgroud)

该功能的行为方式完全相同!记住函数Task<string>不返回string.await这里的关键字是退化吗?编译器是否只是从我的代码中删除它?

Eri*_*ert 7

鉴于您目前的理解水平,这个问题的答案太大了,无法在此发布.你应该做的是先阅读我的MSDN文章,然后阅读Mads的MSDN文章; 它们是该功能的初学者入门,Mads描述了它是如何实现的.你可以在这里找到链接:

http://blogs.msdn.com/b/ericlippert/archive/2011/10/03/async-articles.aspx

然后,如果您对该功能的基础理论感兴趣,您应该首先阅读我关于延续传递风格的所有文章:

http://blogs.msdn.com/b/ericlippert/archive/tags/continuation+passing+style/

从底部开始.一旦理解了延续的概念,您就可以阅读我关于如何设计异步功能的系列文章:

http://blogs.msdn.com/b/ericlippert/archive/tags/async/


Ste*_*ary 6

正如Eric Lippert指出的那样,第一个版本将无法编译; 您必须删除该async关键字,否则您将收到类型错误.

这是一个有用的心智模型,关于asyncawait关键字如何使用返回类型:

  • 方法T返回的任何值async都"包装"到一个Task<T>.
  • await关键字(可以认为的操作者),当应用于Task<T>,将"解开"它,导致类型的值T.

现在,这是一种极端的简化; 实际发生的事情更复杂.例如,这种简化会跳过如何await使用当前的方法SynchronizationContext:在第二个示例中,该方法将尝试在await完成后返回到原始上下文,因此如果该上下文繁忙,您将观察到不同的行为.

但在大多数情况下,这两个例子几乎相同.第二个是由于async状态机而在上下文中恢复的效率较低.

我有一个async/ await介绍,你可能会发现有用; 在那篇文章中,我尝试以async一种不太复杂但实际上也不正确的方式解释.:)