我应该避免“asynchronous无效”事件处理程序?

我知道使用fire-and-forget async void方法来启动任务通常被认为是一个坏主意,因为没有任何待处理任务的轨迹,处理可能在这种方法中抛出的exception是非常棘手的。

我通常应该避免async void事件处理程序? 例如,

 private async void Form_Load(object sender, System.EventArgs e) { await Task.Delay(2000); // do async work // ... } 

我可以像这样改写它:

 Task onFormLoadTask = null; // track the task, can implement cancellation private void Form_Load(object sender, System.EventArgs e) { this.onFormLoadTask = OnFormLoadTaskAsync(sender, e); } private async Task OnFormLoadTaskAsync(object sender, System.EventArgs e) { await Task.Delay(2000); // do async work // ... } 

什么是asynchronous事件处理程序的水下岩石,除了可能的重入?

指南是避免async void 除非在事件处理程序中使用,所以在事件处理程序中使用async void是正常的。

这就是说, unit testing的原因,我经常喜欢把所有async void方法的逻辑async void出来。 例如,

 public async Task OnFormLoadAsync(object sender, EventArgs e) { await Task.Delay(2000); ... } private async void Form_Load(object sender, EventArgs e) { await OnFormLoadAsync(sender, e); } 

我通常应该避免asynchronous无效事件处理程序?

通常,事件处理程序是一种无效的asynchronous方法不是潜在的代码异味的情况。

现在,如果你确实需要跟踪任务出于某种原因,那么你描述的技术是完全合理的。

是的,一般情况下,事件处理程序的asynchronous无效是唯一的情况。 如果你想了解更多关于它的信息,你可以在9频道看看一个很棒的video

The only case where this kind of fire-and-forget is appropriate is in top-level event-handlers. Every other async method in your code should return "async Task".

这里是链接

如果您使用ReSharper,免费的推荐扩展可能对您有所帮助。 它分析了“asynchronous无效”的方法,并强调使用不当。 该扩展可以区分asynchronous无效的不同用法,并提供这里描述的适当的快速修复: ReCommended-Extension wiki 。