【问题标题】:How does c# handle async voidc#如何处理async void
【发布时间】:2017-01-17 08:39:49
【问题描述】:

我通常对网络服务器进行编程,起初我认为必须有连续的方法链来返回任务,所以在堆栈中填充可能会询问数据库是否完成。

最近我看到了 wpf 代码,它做了这样的事情:

    public async void Execute(object parameter)
    {
        await ExecuteAsync(parameter);
    }

在事件处理程序中调用。 UI 似乎是响应式的,所以我想它确实有效。它是如何工作的?这如何转化为 aspnet?

【问题讨论】:

    标签: c# async-await


    【解决方案1】:

    我在我的 Best Practices in Asynchronous Programming 文章中解释了 async void 方法的工作原理 - 以及为什么应该避免使用它们。

    async voidasync Task 具有相同的语义,但例外情况除外。 async void 方法将在方法的开头捕获当前的 SynchronizationContext,并且该方法的任何异常都将被捕获并直接在该捕获的上下文中引发。在最常见的情况下,这将导致应用程序级异常,通常是崩溃。有些人称async void 方法为“即火即忘”,但由于它们的特殊行为,我更喜欢“即火即崩溃”。 :)

    “避免异步无效”是一般准则,但有一个值得注意的例外:事件处理程序(或逻辑上是事件处理程序的项,例如 ICommand.Execute 实现)。

    它是如何工作的?这如何转化为 aspnet?

    它的工作原理与任何其他 async 方法一样。主要的平台区别在于 UI 线程不需要知道async 方法何时完成。 ASP.NET 需要知道这一点,因此它知道何时发送请求,但 UI 不需要知道 async 方法何时完成。所以async void 有效。最好还是避免它,因为调用代码通常确实需要知道它何时完成。

    【讨论】:

      【解决方案2】:

      Async void 仅用于事件处理程序/委托的可比性。 Execute 是一个事件回调,可能来自DelegateCommand 或类似的。

      它的工作方式是将其视为与您有一个返回 Task 的函数完全相同,但调用者从未在该返回的任务上调用 await

      在 ASP.NET 上,您可能永远不会使用 async void,而是使用公开返回 Task<ActionResult> 的方法的控制器、使用 HostingEnviorment.QueueBackgroundWorkItem 或在以下情况下使用封装在 Page.RegisterAsyncTask 中的函数你会在普通的桌面编程中使用async void

      public void Page_Load(object sender, EventArgs e)
      {
          RegisterAsyncTask(new PageAsyncTask(LoadSomeData));
      }
      

      【讨论】:

      • 当我不等待任务时会发生什么?
      • @user2029276 asp.net 子系统不知道该任务,并且可能在函数完成执行之前拆除网站的应用程序域,导致您告诉函数执行的工作丢失并且从未完成。您可以在 WPF 中解决此问题的原因是您的 AppDomain 在用户使用该程序时不会被随机拆除,只要该程序正在运行 AppDomain 就可以继续存在。 asp.net 网站上的非活动用户可能会拆除 AppDomain,甚至不会注意到它发生。
      猜你喜欢
      • 2014-06-17
      • 2014-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-08
      • 2021-12-24
      • 2012-09-02
      相关资源
      最近更新 更多