我知道使用即发即弃 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
// ...
}
除了可能的重入之外,异步事件处理程序的水下岩石是什么?
指导方针是避免在事件处理程序中使用 async void
except,因此在事件处理程序中使用 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);
}
我通常也应该避免使用 async void 事件处理程序吗?
通常,事件处理程序是无效异步方法不是潜在代码异味的一种情况。
现在,如果您出于某种原因确实需要跟踪任务,那么您描述的技术是完全合理的。
是的,通常 async void 的事件处理程序是唯一的情况。如果您想了解更多信息,可以在第 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".
这是link
如果您使用 ReSharper,免费的 ReCommended Extension 可能会对您有所帮助。它分析了“异步无效”方法并在使用不当时突出显示。该扩展可以区分 async void 的不同用法并提供此处描述的适当快速修复:ReCommended-Extension wiki。
Form_Load
对public
的访问权限?看起来这样的代码会不那么冗长。OnFormLoadAsync
的返回类型。我现在看到这是一个方便的技巧。谢谢。Handled
标志 必须 同步设置;无法使用async
来决定是否处理事件。ICommand.Execute
方法async void
;我认为这是可以接受的,因为ICommand.Execute
在逻辑上 是一个事件处理程序。async void
方法都可能无法完成。