[英]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/
从底部开始。 一旦理解了延续的概念,您就可以阅读我关于如何设计异步功能的系列文章:
正如Eric Lippert指出的那样,第一个版本将无法编译; 您必须删除async
关键字,否则您将收到类型错误。
这是一个有用的心理模型,关于async
和await
关键字如何与返回类型一起使用:
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.