是否可以声明异步方法为返回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 …