【问题标题】:Why should a void method be async to be able to await?为什么 void 方法应该是异步的才能等待?
【发布时间】:2014-12-03 18:11:33
【问题描述】:

假设我有一个具有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 关键字是什么意思。
  • 其次,重申我的问题,我不确定为什么它是必需

【问题讨论】:

  • 1) 不能在未声明 async 的方法中使用 await 运算符。因此,它启用操作员。 2)我不确定我是否理解您的问题,“为什么需要它?”这是必需的,因为这就是语言的工作方式。究竟是什么问题?
  • 我的意思是,它应该只是为了符合现有设计吗?设计师不想在这种情况下破例?因为从我的角度来看,它不是必需的。该方法可以正常工作,而调用者不需要知道它是async

标签: c# async-await


【解决方案1】:

异步方法必须标记为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 operator must be within an async method”错误时,您的默认反应应该是将其标记为async 并且将返回类型从void更改为Task

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

这遵循了我的MSDN article on the subject 中的最佳实践之一:避免使用async voidasync void 被语言设计者允许用于事件处理程序(或逻辑上为事件处理程序的代码,例如ICommand.Execute);任何其他用法都会导致问题。

【讨论】:

    【解决方案2】:

    我不明白为什么。

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

    编译器可以推断您的方法是否包含任何await 表达式 - 但这意味着您可以注释掉方法的一行,整个方法的行为将彻底改变。 (想想异常处理,例如......)

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

    所以基本上,答案是:

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

    【讨论】:

    • 乔恩,有这个副本吗?如果没有,那么这可能会成为规范的“为什么我需要让我的方法async”问题。
    • @JohnSaunders:不是我知道的副手。可能有,但我现在不知道 :)
    • @JohnSaunders 在我看来,这个问题的规范参考是Eric's blog post。它包括对 Jon 在这里总结的要点的更深入的探索,以及其他一些内容,例如避免破坏性更改(如果有人有一个名为 await pre-5.0 的方法呢?)。
    【解决方案3】:

    因为它们必须在 C# 中成对工作。这是规矩。

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

    【讨论】:

      猜你喜欢
      • 2023-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 2019-01-28
      • 1970-01-01
      • 2017-03-21
      相关资源
      最近更新 更多