繁体   English   中英

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

[英]What happens when you await a Task before returning it?

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

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

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

return await client.GetStringAsync(pageAddress);

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

鉴于您目前的理解水平,这个问题的答案太大了,无法在此发布。 你应该做的是先阅读我的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/

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

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

  • async方法返回的任何值T都“包装”到Task<T>
  • 当应用于Task<T>await关键字(您可以将其视为运算符)将“解包”它,从而产生类型为T的值。

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

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

我有一个async / await介绍 ,你可能会觉得有帮助; async文章中,我尝试以一种不太复杂但实际上也不正确的方式解释async :)

埃里克显然是这里的专家,他的建议很合理,但回答你的具体问题:

在第一个版本中, async的方法关键字是不相关的,你GetStringAsync方法返回相同的Task<string> awaitable多数民众赞成由返回client.GetStringAsync

在第二个版本中,方法上的async关键字是必需的,因为您在方法中使用await并且await关键字创建并返回一个单独的Task<string> ,等待来自client.GetStringAsync完成。 发生这种情况时, await client.GetStringAsync异步获取的字符串,该字符串作为异步方法的结果返回。

所以对于GetStringAsync的调用者来说,它们在功能上是相同的,但第一个版本更清晰。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM