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

ato*_*erz 4 c# async-await

假设我有一个void返回类型的方法,我需要await在此方法中进行操作.

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

当我尝试编译此代码时,我得到了错误说someOperation必须声明async.我不明白为什么.我理解为什么如果方法有一个返回值,但是当它的时候没有void.甚至在等待操​​作对方法的返回值没有影响的情况下.
这已经被问到这个问题的一部分,但我找不到我想要的答案.这家伙只是提到:

async关键字启用await关键字.因此,任何使用await的方法都必须标记为异步.

  • 首先,我不确定async关键字启用await关键字是什么意思.
  • 其次,重申我的问题,我不确定为什么需要它?

Jon*_*eet 11

我不明白为什么.

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

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

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

所以基本上,答案是:

  • 您需要,因为语言规范要求您.编译器正在实现语言规范.
  • 语言规范要求你,因为它减少了惊喜的元素.


Ste*_*ary 11

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

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

我有一篇关于这个主题博客文章,链接到Eric Lippert的权威博客文章,以及博客评论,Channel9论坛,MSDN论坛的讨论,当然还有Stack Overflow.

请注意,没有结果值的方法的自然返回类型不是.是一种不自然的方法返回类型.因此,当看到"await运算符必须在异步方法中"错误时,您的默认反应应该是标记它并将返回类型更改为:asyncTaskvoidvoidasyncasync voidTask

public async Task someOperationAsync()
{
  //dostuff
  var res = await someOtherOperationAsync();
  //do some other stuff that needs res.
}
Run Code Online (Sandbox Code Playgroud)

这遵循我的MSDN文章中关于该主题的最佳实践之一:避免async void.async void允许由语言的设计者事件处理程序(或代码,逻辑上的事件处理程序,等ICommand.Execute); 任何其他用法都会导致问题.