为什么void方法必须异步才能等待?

时间:2014-12-03 18:11:34

标签: c# async-await

假设我的方法具有void返回类型,并且我需要await对此方法中的操作进行操作。

public void someOperation()
{
    //dostuff
    var res = await someOtherOperation();
    //do some other stuff that needs res.
}

当我尝试编译此代码时,我收到错误消息,指出someOperation必须声明为async。我不明白为什么。我明白为什么如果该方法有一个返回值,但是当它的void时没有。或者甚至在等待操​​作对方法的返回值没有影响的情况下 这已被问及this问题的一部分,但我找不到我想要的答案。 This guy仅提及:

  

async关键字启用await关键字。所以使用等待的任何方法   必须标记为异步。

  • 首先,我不确定async关键字启用await关键字的含义。
  • 其次,重述我的问题,我不确定为什么必需

3 个答案:

答案 0 :(得分:11)

  

我不明白为什么。

因为您需要告诉编译器您正在尝试编写异步方法。这正是你引用的文件的意思。

编译器可以推断出你的方法是否包含任何await表达式 - 但这意味着你可以注释掉一行方法,整个方法的行为会< em>从根本上改变。 (考虑例外处理,例如......)

它还提高了可读性 - 这意味着任何阅读代码的人都知道这是一种异步方法。

基本上,答案是:

  • 您需要,因为语言规范要求您。编译器正在实现语言规范。
  • 语言规范要求你,因为它减少了意外因素。

答案 1 :(得分:11)

必须将异步方法标记为asyncasyncawait个关键字配对在一起,主要是出于向后兼容的原因; await是有效的标识符(不是关键字),因此当它添加到语言中时,他们还添加了async关键字。

或者,他们可以使用await的多字关键字,例如await for。然而,语言设计团队决定采用配对,因为它清楚明确地标记了所有async方法 - 编译器和人类都更容易解析。

我有一个blog post on the subject,其中包含Eric Lippert's definitive blog post的链接以及blog commentsChannel9 forumsMSDN forums,当然还有right here on Stack Overflow的讨论}。

请注意,没有结果值的async方法的自然返回类型为Task,而不是voidvoidasync方法的非自然返回类型。因此,当看到“await运算符必须在异步方法中”错误时,您的默认反应应该是标记async 将返回类型从void更改为{{1 }}:

Task

这遵循我的MSDN article on the subject中的最佳做法之一:避免public async Task someOperationAsync() { //dostuff var res = await someOtherOperationAsync(); //do some other stuff that needs res. } 。语言设计者为事件处理程序(或逻辑上的事件处理程序的代码,如async void允许 ;任何其他用法都会导致问题。

答案 2 :(得分:0)

  

因为它们必须在C#中成对使用。这是规则。

“async”关键字在该方法中启用“await”关键字,并更改方法结果的处理方式。这就是async关键字的全部功能!它不会在线程池线程上运行此方法,也不会执行任何其他类型的魔术。 async关键字仅启用await关键字(并管理方法结果)。