async void
事件处理程序:该不该避免?
一般来说,最佳实践建议避免使用 async void
方法,尤其是在启动任务时,因为它们缺乏跟踪挂起任务的机制,并且异常处理较为复杂。但是,这个原则是否也适用于 async void
事件处理程序呢?
让我们来看一个例子:
<code class="language-csharp">private async void Form_Load(object sender, System.EventArgs e) { await Task.Delay(2000); // 执行异步操作 // ... }</code>
与其使用这种方法,不如重新设计代码来实现任务跟踪和取消功能:
<code class="language-csharp">Task onFormLoadTask = null; // 跟踪任务,可以实现取消 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); // 执行异步操作 // ... }</code>
除了潜在的重入问题外,async void
事件处理程序还有什么隐藏的陷阱?
关键在于,async void
的使用在无法优雅地处理异常的上下文中是被劝退的。然而,在事件处理程序中,异常会被路由到全局异常处理程序,确保它们被适当地捕获和处理,无需在事件处理程序本身进行显式错误处理。这就是使 async void
在这种特定情况下可以接受的关键区别。
为了进行单元测试,通常的做法是提取所有 async void
方法的逻辑以进行隔离:
<code class="language-csharp">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); }</code>
总之,虽然通常不建议使用 async void
方法,但在 async void
事件处理程序中使用它们是可以接受的,因为事件处理程序框架具有固有的异常处理机制。因此,您可以在事件处理程序中使用 async void
而不会违反最佳实践。
以上是您应该避免使用 Async Void 事件处理程序吗?的详细内容。更多信息请关注PHP中文网其他相关文章!