【问题标题】:What happens when you await a Task before returning it?当您在返回任务之前等待任务时会发生什么?
【发布时间】:2013-07-06 14:45:09
【问题描述】:

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

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

我知道我正在返回 Task&lt;String&gt; 并且可以等待其他方法的结果。这种方法效果很好。我的问题是当我将上述函数的第二行替换为以下内容时会发生什么(实际上是在幕后)(注意 await 关键字的引入):

return await client.GetStringAsync(pageAddress);

函数的行为方式完全相同!请记住,该函数返回 Task&lt;string&gt; 而不是 stringawait 这里的关键字是不是退化了?编译器是否只是从我的代码中删除它?

【问题讨论】:

标签: c# asynchronous async-await


【解决方案1】:

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

【讨论】:

【解决方案2】:

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

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

  • async 方法返回的任何值 T 都会“包装”到 Task&lt;T&gt; 中。
  • await 关键字(您可以将其视为运算符)在应用于 Task&lt;T&gt; 时将“展开”它,从而产生 T 类型的值。

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

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

我有一个async/await intro,您可能会觉得有帮助;在那篇文章中,我尝试以一种不太复杂但实际上也不是不正确的方式来解释async。 :)

【讨论】:

    【解决方案3】:

    Eric 显然是这里的专家,他的建议是合理的,但要回答您的具体问题:

    在第一个版本中,方法上的 async 关键字无关紧要,您的 GetStringAsync 方法返回与 client.GetStringAsync 返回相同的 Task&lt;string&gt; 等待。

    在第二个版本中,方法上的 async 关键字是必需的,因为您在方法中使用了 await,并且 await 关键字创建并返回一个单独的 Task&lt;string&gt; 可等待对象,该等待对象在等待时完成client.GetStringAsync 完成。发生这种情况时,await 会计算出由client.GetStringAsync 异步获取的字符串,该字符串作为异步方法的结果返回。

    所以对于GetStringAsync的调用者来说,它们在功能上是一样的,但是第一个版本更简洁。

    【讨论】:

      猜你喜欢
      • 2012-09-11
      • 2014-11-22
      • 2019-04-29
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      相关资源
      最近更新 更多