我正在试验新的异步,并等待关键字。我产生了以下异步函数:
private async static Task<string> GetStringAsync(string pageAddress)
{
HttpClient client = new HttpClient();
return client.GetStringAsync(pageAddress);
}我知道我正在返回一个Task<String>,可以等待另一个方法的结果。这种方法效果很好。我的问题是,当我将上述函数的第二行替换为以下内容(注意引入“等待”关键字)时,会发生什么情况?
return await client.GetStringAsync(pageAddress);该函数的行为方式完全相同!记住,函数返回的是Task<string>,而不是string。这里的await关键字是否退化?编译器会直接从我的代码中删除它吗?
发布于 2013-07-06 18:21:49
正如Eric所指出的,第一个版本不会编译;您必须删除async关键字,否则会出现类型错误。
下面是一个关于async和await关键字如何与返回类型一起工作的有用的心智模型:
T方法返回的任何值都被“包装”到Task<T>中。await关键字(您可以将其视为运算符)在应用于Task<T>时,将“展开”它,从而生成T类型的值。现在,这是一个极端的简化;实际上正在发生的事情更加复杂。例如,这个简化将跳过await与当前SynchronizationContext的工作方式:在第二个示例中,该方法将尝试在await完成后返回到原始上下文,因此如果该上下文繁忙,您将观察到不同的行为。
但在大多数情况下,这两个例子几乎是等同的。由于async状态机和上下文恢复,第二种方法的效率较低。
我有一个 intro,您可能会发现它很有帮助;在那篇文章中,我试图以一种不太复杂但实际上也不正确的方式解释async。:)
发布于 2013-07-06 15:27:41
鉴于你目前的理解水平,这个问题的答案太大了,不能在这里发布。您应该从阅读我的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/
发布于 2013-07-06 16:19:17
埃里克显然是这里的专家,他的建议是合理的,但要回答你的具体问题:
在第一个版本中,方法上的async关键字无关紧要,您的GetStringAsync方法返回与client.GetStringAsync返回的相同的Task<string>。
在第二个版本中,方法上的async关键字是必需的,因为您在方法中使用了await,而await关键字创建并返回了一个单独的Task<string> awaitable,该Task<string>在client.GetStringAsync完成后完成。当发生这种情况时,await计算为client.GetStringAsync异步获得的字符串,该字符串作为异步方法的结果返回。
因此,对于GetStringAsync的调用者来说,它们在功能上是相同的,但是第一个版本更干净。
https://stackoverflow.com/questions/17504002
复制相似问题