避免异步无效
-
唯一可以安全使用
async void
的地方是事件处理程序。请考虑以下代码:private async Task<bool> SomeFuncAsync() { ... await ... } public void button1_Click(object sender, EventArgs e) { var result = SomeFuncAsync().Result; SomeOtherFunc(); }
一旦
async
呼叫完成,它将等待SynchronizationContext
变为可用。但是,事件处理程序在等待SomeFuncAsync
方法完成时保持SynchronizationContext
; 从而导致循环等待(死锁)。要解决这个问题,我们需要将事件处理程序修改为:
public async void button1_Click(object sender, EventArgs e) { var result = await SomeFuncAsync(); SomeOtherFunc(); }
-
任何从
async void
方法抛出的异常将直接在async void
方法启动时激活的SynchronizationContext
上引发。private async void SomeFuncAsync() { throw new InvalidOperationException(); } public void SomeOtherFunc() { try { SomeFuncAsync(); } catch (Exception ex) { Console.WriteLine(ex); throw; } }
这个例外永远不会被
SomeOtherFunc
中的 catch 块捕获。 -
async void
方法没有提供一种简单的方法来通知他们已经完成的调用代码 -
async void
方法很难测试。MSTest 异步测试支持仅适用于返回Task
或Task<T>
的async
方法。