避免异步无效
-
唯一可以安全使用
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方法。