async void事件处理程序 - 澄清?

时间:2014-05-01 11:00:35

标签: c# asp.net async-await .net-4.5 c#-5.0

我试图理解为什么不好做的原因:(注意,这里的上下文是asp.net,不管async void的原因是什么无法跟踪

 public async void Page_Load(object sender, EventArgs e)
{
 ...
}

嗯,经过调查,我发现很少有不同的原因:

  • Damian Edwards说:here

      

    Web表单中的异步void事件处理程序仅在某些情况下受支持   事件,正如您所发现的那样,但实际上只是为了简单化   任务。我们建议使用PageAsyncTask进行任何真实的异步工作   复杂性。

  • Levi说here

      

    Web应用程序中的异步事件本身就是一种奇怪的野兽。异步   void意味着火,忘记编程模型。这适用于   Windows UI应用程序自应用程序以来一直坚持到   操作系统会杀死它,因此每当异步回调运行时都会保证   是一个可以与之交互的UI线程。在Web应用程序中,这个   模型分崩离析,因为请求是按定义瞬态的。 如果   异步回调碰巧在请求完成后运行,有   无法保证回调需要交互的数据结构   仍处于良好状态。因此,为什么火和忘记(和异步   在Web应用程序中本身就是一个坏主意。

         

    那就是说,我们做疯狂的体操,试图做出非常简单的事情   像Page_Load工作,但支持这一点的代码非常   对于基本场景之外的任何事情都很复杂且没有经过良   因此,如果您需要可靠性,我会坚持使用RegisterAsyncTask。

  • This site说:

      

    我们知道   我们的页面生命周期有一组在a中被触发的事件   预定义的订单和下一个事件将仅在最后一个事件时触发   完成。因此,如果我们使用上述方式的异步Page_Load,这个事件   一旦达到异步,将在页面生命周期事件期间触发,   当前线程获得释放,另一个线程被分配完成   该任务是异步的,但是ASP.NET无法执行下一个事件   在生命周期中,因为Page_Load还没有完成。和   底层同步上下文等待直到异步   活动完成。然后只有页面生命周期的下一个事件   已触发,仅使整个过程处于同步模式。

  • This网站说

      

    当返回类型为void时,   调用者可能会认为该方法在返回时已完成。   这个问题可能以许多意想不到的方式出现。这通常是错的   提供void返回的异步实现(或覆盖)   接口(或基类)上的方法。 有些事件也会假设   他们的处理程序在返回时完成

我在这里看到非常不同(非重叠)的原因。

问题:

什么是我们不应该写public async void Page_Load(object sender, EventArgs e)的荣耀/真正原因?


nb,我也不知道为什么这是一个问题,因为4.5确实使用了UseTaskFriendlySynchronizationContextaim is to support

protected async void Page_Load(object sender, EventArgs e){...}

2 个答案:

答案 0 :(得分:5)

您链接的文章使原因非常清楚。不要使用它,因为除了最基本的场景之外它不可靠。我们可以在异步void方法中引入同步上下文,只有很多异步跟踪技巧。我们确实努力使这些基本方案工作,但我们的一般指导是避免使用它们,而是明确地注册异步工作。

答案 1 :(得分:2)

我还没有对此进行验证,但我觉得在ASP.NET 4.5 WebForms中使用async void Page_Load(...)是可以的,因为只要页面有{ {1}}声明。

我认为这是基于implementation of AspNetSynchronizationContext.OperationStarted,当在<%@ Page Async="true" ... %>的线程上调用任何async void方法时调用{{3}}。以下是相关评论:

AspNetSynchronizationContext

显然, // If the caller tries to kick off an asynchronous operation while we are not // processing an async module, handler, or Page, we should prohibit the operation. 的网页不违反此要求,并且在所有待处理操作完成之前,HTTP请求处理不会完成,包括Async="true"个。