当前位置: 首页 > 知识库问答 >
问题:

为什么void异步不好?

祁权
2023-03-14

所以我理解为什么从异步返回空洞通常没有意义,但我遇到了一种我认为完全有效的情况。请考虑以下人为的示例

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);
}

我意识到这是一个不寻常的例子,但我试图使其简单化和更普遍化。有人能向我解释为什么这是可怕的代码,以及我如何修改它以正确遵循约定吗?

谢谢你的任何帮助。

共有2个答案

谯灿
2023-03-14

使用void async通常被视为“不好”,因为:

    < li >你不能等待它的完成(正如在这篇文章中已经提到的那样 < li >如果被一个在其完成之前就退出的父线程调用,将会非常痛苦 < li >任何未处理的异常都将终止您的进程(哎哟!)

有很多情况(像你一样)使用它是可以的。使用时要小心。

邬弘化
2023-03-14

好吧,看看“避免< code >异步无效”一文中的原因:

  • 异步void方法具有不同的错误处理语义。从<code>PrimeCustomTask
  • 异步void方法具有不同的组成语义。这是一个围绕代码可维护性和重用的争论。本质上,PrimeCustomTask中的逻辑就在那里,就是这样-它不能被组合成更高级的async方法
  • 异步void方法很难测试。自然地,从前两点开始,编写包含<code>PrimeCustomTask

同样重要的是要注意,异步任务是自然的方法。在采用异步/等待的几种语言中,C#/VB 是唯一支持异步 void 的 AFAIK 语言。F#没有,蟒蛇没有,JavaScript和类型脚本没有。从语言设计的角度来看,异步虚空是不自然的。

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

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

private async Task PrimeCustomTask()

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

 类似资料:
  • 问题内容: 经过一整天的研究和尝试,我终于放弃了 纯AJAX的 上传文件(ps:本文如何与JQuery异步上传文件?埋了我的最后希望) 我的问题可能没什么意义,但是我仍然想知道为什么ajax(或XMLHttpRequest)不能处理这个问题?为什么文件不能像真正的httprequest那样传输? 问题答案: 出于安全原因,JavaScript无法读取本地文件,因此我们无法使用AJAX发送数据。 但

  • 问题内容: 为什么将AJAX称为异步?它如何完成与服务器的异步通信? 问题答案: 它是异步的,因为它不会锁定浏览器。如果您触发Ajax请求,则用户在等待响应时仍可以工作。当服务器返回响应时,将运行一个回调来处理它。 您可以根据需要进行同步,如果需要,可以在请求未完成时将浏览器锁定(因此,大多数情况下这是不合适的)

  • 我得到以下警告... 警告1此异步方法缺少await运算符,将同步运行。考虑使用'await'运算符来等待非阻塞API调用,或者使用'await task.run(...)'在后台线程上执行CPU绑定的工作。

  • 我刚刚发现,在react函数都是异步的,或者在调用它的函数完成后调用。 现在这两样东西很难消化 在博客中,函数是在函数内部调用的,但是触发函数的原因并不是被调用函数所知道的。 他们为什么要让异步,因为JS是单线程语言,而且这个setState不是WebAPI或服务器调用,所以只能在JS的线程上完成。他们这样做是为了使重新呈现不会停止所有事件侦听器和其他东西,还是有其他设计问题。

  • 我一直在遵循一个教程,并遇到了以下代码片段: 响应到JSON对象的转换不应该立即发生吗?从数组(例如中获取值的方法也应该如此吗?为什么需要等待用户响应。json()和?

  • 然而,在我下面的代码中,我希望在这两个示例中都花费相同的15秒(每个任务5秒),如本文所述。然而,第二个示例只需要5秒,同时运行所有3个示例也需要5秒来完成第二个示例。原来的文章花了5秒,但我把它改成了1秒的延迟,让它更明显。 有没有人能解释一下这是怎么回事,为什么它看起来像线程一样运行?