async void
不能被追踪的简单原因)。 public async void Page_Load(object sender, EventArgs e)
{
...
}
好的,经过一番调查,我发现有几个不同的原因:
Damian Edwards在这里表示:Web Forms中的异步void事件处理程序仅支持某些事件,但实际上只适用于简单任务。我们建议对任何真正复杂的异步工作使用PageAsyncTask。
Levi在这里表示:Web应用程序中的异步事件本质上是奇怪的东西。异步void适用于一种“启动并忘记”编程模型。这在Windows UI应用程序中起作用,因为应用程序会一直存在,直到操作系统终止它,因此每当异步回调运行时,都有保证可与之交互的UI线程。在Web应用程序中,此模型崩溃了,因为请求定义为瞬态的。如果异步回调恰好在请求完成后运行,就没有保证回调需要与之交互的数据结构仍然处于良好状态。因此,“启动并忘记”(和异步void)在Web应用程序中本质上是一个坏主意。尽管如此,我们做出了非常简单的事情,例如Page_Load,但支持此操作的代码极其复杂,并且未经过非常基本场景的测试。因此,如果您需要可靠性,则应坚持使用RegisterAsyncTask。
这个网站表示:
我们知道,我们的页面生命周期具有一组按预定义顺序触发的事件,只有在上一个事件完成后才会触发下一个事件。因此,如果我们使用上述异步Page_Load的方式,在它到达异步时将触发此事件,当前线程将释放,另一个线程被指定为异步完成任务,但ASP.NET不能执行生命周期中的下一个事件,因为Page_Load尚未完成。底层同步上下文等待异步活动完成。然后,仅当页面生命周期的下一个事件被触发时,整个过程才处于同步模式。
这个网站表示:
当返回类型为void时,调用者可能假设方法在返回时已完成。此问题可能以许多意想不到的方式出现。通常在接口(或基类)上提供异步实现(或重写)void返回方法是错误的。有些事件还假定其处理程序在返回时已完成。
我在这里看到非常不同(不重叠)的原因。
问题:
为什么我们不应该编写public async void Page_Load(object sender, EventArgs e)
?
注意,我也不知道为什么这是一个问题,因为4.5使用UseTaskFriendlySynchronizationContext,它的目的是支持:
protected async void Page_Load(object sender, EventArgs e){...}
async void
,而所有与非ASP相关的链接都说你应该非常小心。这应该告诉你一些事情,即ASP很特殊。如果你阅读一些自己的链接,它们甚至会解释为什么ASP很特殊,以及它是如何允许async void
方法按照你所希望的方式工作的;当然,这仅适用于简单的情况;它还解释了什么情况下它不起作用以及该怎么做。 - Servy