为什么 void async 是坏的? [英] Why exactly is void async bad?

查看:28
本文介绍了为什么 void async 是坏的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我理解为什么从 async 返回 void 通常没有意义,但我遇到了一种我认为它完全有效的情况.考虑以下人为的例子:

So I understand why returning void from async would normally make no sense, but I've ran into a situation where I think it would be perfectly valid. Consider the following contrived example:

protected override void OnLoad(EventArgs e)
{
    if (CustomTask == null)
        // Do not await anything, let OnLoad return.
        PrimeCustomTask();
}
private TaskCompletionSource<int> CustomTask;

// I DO NOT care about the return value from this. So why is void bad?
private async void PrimeCustomTask()
{
    CustomTask = new TaskCompletionSource<int>();
    int result = 0;
    try
    {
        // Wait for button click to set the value, but do not block the UI.
        result = await CustomTask.Task;
    }
    catch
    {
        // Handle exceptions
    }
    CustomTask = null;

    // Show the value
    MessageBox.Show(result.ToString());
}

private void button1_Click(object sender, EventArgs e)
{
    if (CustomTask != null)
        CustomTask.SetResult(500);
}

我意识到这是一个不寻常的例子,但我试图让它变得简单和概括.有人可以向我解释为什么这是可怕的代码,以及我如何修改它以正确遵循约定?

I realize this is an unusual example, but I tried to make it simple and more generalized. Could someone explain to me why this is horrible code, and also how I could modify it to follow conventions correctly?

感谢您的帮助.

推荐答案

好吧,在 避免async void"文章:

Well, walking through the reasons in the "avoid async void" article:

  • 异步 void 方法具有不同的错误处理语义.从 PrimeCustomTask 转义的异常将很难处理.
  • 异步 void 方法具有不同的组合语义.这是一个围绕代码可维护性和重用性的论点.本质上,PrimeCustomTask 中的逻辑就在那里,仅此而已 - 它不能组合成更高级别的 async 方法.
  • 异步 void 方法难以测试.自然地从前两点开始,编写一个涵盖 PrimeCustomTask(或任何调用它的东西)的单元测试是非常困难的.
  • Async void methods have different error-handling semantics. Exceptions escaping from PrimeCustomTask will be very awkward to handle.
  • Async void methods have different composing semantics. This is an argument centered around code maintainability and reuse. Essentially, the logic in PrimeCustomTask is there and that's it - it can't be composed into a higher-level async method.
  • Async void methods are difficult to test. Following naturally from the first two points, it's very difficult to write a unit test covering PrimeCustomTask (or anything that calls it).

同样重要的是要注意 async Task 是一种自然的方法.在几种采用async/await的语言中,C#/VB 是唯一支持 async void 的 AFAIK.F# 没有,Python 没有,JavaScript 和 TypeScript 没有.async void 从语言设计的角度来看是不自然的.

It's also important to note that async Task is the natural approach. Of the several languages that have adopted async/await, C#/VB are the only ones AFAIK that support async void at all. F# doesn't, Python doesn't, JavaScript and TypeScript don't. async void is unnatural from a language design perspective.

async void 添加到 C#/VB 的原因是为了启用异步事件处理程序.如果您更改代码以使用 async void 事件处理程序:

The reason async void was added to C#/VB was to enable asynchronous event handlers. If you change your code to use async void event handlers:

protected override async void OnLoad(EventArgs e)
{
  if (CustomTask == null)
    await PrimeCustomTask();
}

private async Task PrimeCustomTask()

那么 async void 的缺点仅限于您的事件处理程序.特别是,来自 PrimeCustomTask 的异常会自然地传播到它的(异步)调用者(OnLoad),PrimeCustomTask 可以组合(从其他异步调用自然地调用)方法),并且 PrimeCustomTask 更容易包含在单元测试中.

Then the async void disadvantages are restricted to your event handler. In particular, exceptions from PrimeCustomTask are propagated naturally to its (asynchronous) callers (OnLoad), PrimeCustomTask can be composed (called naturally from other asynchronous methods), and PrimeCustomTask is much easier to include in a unit test.

这篇关于为什么 void async 是坏的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆