2014-12-03 34 views
4

假设我有一个方法,它具有void返回类型,我需要await对此方法的操作。为什么一个void方法是异步的以便能够等待?

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

当我试图编译这段代码,我得到了错误说someOperation必须申报async。我不明白为什么。我明白为什么如果该方法具有返回值,但在void时不在此处。甚至在等待操​​作对方法的返回值没有影响的情况下也是如此。
这已经被作为this问题的一部分提出,但我没有找到我正在寻找的答案。 This guy仅提及:

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

  • 首先,我不知道这意味着什么是async关键字,可以await关键字。
  • 其次,重申我的问题,我不确定为什么它是需要
+2

1)您不能在未声明为'async'的方法中使用'await'运算符。因此它*使*操作员。 2)我不确定我明白你的问题是什么,“为什么这是必需的?”这是必需的,因为这是该语言的工作原理。究竟是什么问题? – 2014-12-03 18:13:40

+0

我的意思是,它应该在那里才符合现有设计?在这种情况下,设计师不想要例外吗?因为从我看它的方式来看它并不是必需的。如果调用者不需要知道它是'async',那么该方法就可以正常工作。 – atoMerz 2014-12-03 18:16:46

回答

11

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

或者,他们可能用了一个多字的关键字为await,如await for。但是,语言设计团队决定采用这种配对方式,因为它清楚明确地标记了所有方法 - 编译器和人员都可以更轻松地进行分析。

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

注意,一个async方法的无的结果值的天然返回类型Task,不voidvoidasync方法的非自然返回类型。所以,在看到“等待操作者必须是异步方法中的”当你默认反应的错误应该是将其标记为async返回类型从voidTask改变:

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);任何其他用法都会导致问题。

11

我不明白为什么。

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

编译器可以推断,从你的方法是否包含任何await表达 - 但是这将意味着你可以注释掉的方法之一线和整个方法的行为将根本变化。 (想想异常处理,例如...)

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

所以基本上,答案是:

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

乔恩,有没有这个副本?如果没有,那么这可能会成为规范的“为什么我需要使我的方法'异步'”的问题。 – 2014-12-03 18:15:57

+0

@JohnSaunders:不是我知道的副手。有可能是,但我现在不知道它:) – 2014-12-03 18:16:50

+0

@JohnSaunders在我脑海中的标准参考是[Eric的博客文章](http://blogs.msdn.com/b/ericlippert/) archive/2010/11/11/whither-async.aspx)。它包括更深入地阐述乔恩在这里总结的观点以及其他几个观点,比如避免突然的变化(如果某人在5.0之前有一种叫做“await”的方法呢?)。 – Servy 2014-12-03 18:57:03

0

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

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