为什么空异步到底是坏的? [英] Why exactly is void async bad?

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

问题描述

所以我理解为什么从异步返回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.

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

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