是否可以声明异步方法为返回void以使CS4014警告静音?

Visual Studio会发出此代码的警告(’因为不等待此调用,在调用完成之前会继续执行当前方法’)。

static void Main(string[] args) { FireAndForget(); // <-- Warning CS4014 // Do something else. } static async Task FireAndForget() { // Do something (cannot throw). } 

我的理解是,在这种特殊情况下不等待任务是可以的,因为FireAndForget永远不会抛出exception。

我没有考虑使用pragma禁用警告,而是考虑将FireAndForget的返回类型从Task更改为void。 这有效地使编译器沉默。

 static async void FireAndForget() // <-- Task changed to void { // Do something (cannot throw). } 

但是,根据Stephen Cleary的说法,应该避免使用“async void”方法,所以我不太清楚该怎么做。

如果方法不是设计为首先等待并且没有抛出exception,那么是否可以使用’async void’方法?

拥有真正的“即发即忘”操作极为罕见; 也就是说,一个操作:

  • 完成时无人关心。
  • 没有人关心它是否完成。
  • 没有人关心它是否会引发exception。

特别是最后一个; 大多数所谓的“即发即忘”操作实际上并不是“一劳永逸”,因为如果不成功就需要采取一些行动。

也就是说,在某些情况下,真正的“即发即弃”是适用的。

我更喜欢使用async Task并通过将任务分配给其他未使用的变量来避免编译器警告:

 var _ = FireAndForget(); 

async Task方法比async void方法更具可重用性和可测试性。

但是,如果我团队中的开发人员只使用async void ,我就不async void

如果方法不是设计为首先等待并且没有抛出exception,那么是否可以使用’async void’方法?

虽然这样做可能“没问题”,但我仍然鼓励你将方法设为async Task 。 尽管你百分之百地确定这种方法不会抛出,并且无法等待,但你永远不知道它最终会被如何使用。 你现在已经充分意识到使用async void的后果是什么了,但是如果将来有人可能需要使用它,那么你最好对这个Task不是为什么不好评论。正在等待,而不是走这条void的简单道路。

不要让编译器警告担心你,我会担心这可能对你的代码库产生正确性和影响。

一个潜在的问题是,现在无法判断代码是否引发了exception。 因此,如果你有unit testing来检测这些,unit testing永远不会工作。

来自MSDN网站的经典示例:

 private async void ThrowExceptionAsync()
 {
  抛出新的InvalidOperationException();
 }
 public void AsyncVoidExceptions_CannotBeCaughtByCatch()
 {
  尝试
   {
     ThrowExceptionAsync();
   }
   catch(例外)
   {
     //这个例外从未在这里发现过!
    扔;
   }
 }

http://haacked.com/archive/2014/11/11/async-void-methods/

https://msdn.microsoft.com/en-us/magazine/jj991977.aspx

如果这是一个特定的边缘情况,而不是使用async void ,那么使用pragma语句怎么样?

 #pragma warning disable CS-4014 ... your code here ... #pragma warning restore CS-4014 

这样你就可以调出静电噪声。

HTH …