我试图理解为什么不好做的原因:(注意,这里的上下文是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。
我们知道 我们的页面生命周期有一组在a中被触发的事件 预定义的订单和下一个事件将仅在最后一个事件时触发 完成。因此,如果我们使用上述方式的异步Page_Load,这个事件 一旦达到异步,将在页面生命周期事件期间触发, 当前线程获得释放,另一个线程被分配完成 该任务是异步的,但是ASP.NET无法执行下一个事件 在生命周期中,因为Page_Load还没有完成。和 底层同步上下文等待直到异步 活动完成。然后只有页面生命周期的下一个事件 已触发,仅使整个过程处于同步模式。
This网站说
当返回类型为void时, 调用者可能会认为该方法在返回时已完成。 这个问题可能以许多意想不到的方式出现。这通常是错的 提供void返回的异步实现(或覆盖) 接口(或基类)上的方法。 有些事件也会假设 他们的处理程序在返回时完成。
我在这里看到非常不同(非重叠)的原因。
问题:
什么是我们不应该写public async void Page_Load(object sender, EventArgs e)
的荣耀/真正原因?
nb,我也不知道为什么这是一个问题,因为4.5确实使用了UseTaskFriendlySynchronizationContext的aim is to support:
protected async void Page_Load(object sender, EventArgs e){...}
答案 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"
个。