我应该避免使用“异步无效”事件处理程序吗?


118

我知道使用即弃即用async void方法启动任务通常被认为是一个坏主意,因为没有跟踪待处理任务的信息,并且处理此类方法中可能引发的异常非常棘手。

我是否也应该一般避免使用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
        // ...
} 

除了可能重新进入之外,异步事件处理程序还有哪些水下岩石?


您应该但不能。除此之外,UI事件处理程序已经要求您在使用异步void时必须采取的所有措施。
Paulo Morgado

而重入发生的原因是事件处理程序触发了异步操作,而不是由于本身未使用async-await。
Paulo Morgado

Answers:


152

准则是避免在事件处理程序中使用时async void 除外,因此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);
}

我很好奇...您为什么不仅仅改变Form_Load对它的访问权限public?看起来该代码不太那么冗长。
InteXX

糟糕,没关系... VBer在这里尝试读取C#...我只是注意到的返回类型OnFormLoadAsync。我现在看到这很方便。谢谢。
InteXX

所有这些,请您在这里看看并提出意见。谢谢!
InteXX

2
@ AlexHopeO'Connor:必须同步设置Handled标志;无法用来决定是否处理该事件。async
Stephen Cleary

1
@ AlexHopeO'Connor:自从我使用WPF应用程序已有一段时间了,但是我使用的解决方案与过去类似。即,制作ICommand.Execute方法async void;我认为这是可以接受的,因为ICommand.Execute逻辑上是事件处理程序。
斯蒂芬·克莱里

49

我是否通常也应该避免使用异步void事件处理程序?

通常,事件处理程序是无效异步方法不会引起代码潜在错误的一种情况。

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


6

是的,通常情况下,没有事件处理程序的异步无效是唯一的情况。如果您想进一步了解它,可以在第9频道观看精彩视频

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".

这是链接


顶级事件处理程序 ”是一个重要提示。在较低级别的事件处理程序上使用异步void事件处理程序时,可能会导致未捕获异常的巨大问题。
Portikus

感谢您的视频链接,非常有用
lsp

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.