【发布时间】:2014-06-17 20:28:56
【问题描述】:
我正在尝试理解 为什么 这样做不好的原因:(注意,这里的上下文是 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 应用程序中,这 模型分崩离析,因为根据定义,请求是瞬态的。 如果 异步回调恰好在请求完成后运行,有 不保证回调需要交互的数据结构 与仍处于良好状态。因此,为什么一发不可收拾(和异步 void) 在 Web 应用程序中本质上是一个坏主意。
也就是说,我们做疯狂的体操是为了尝试做一些非常简单的事情 喜欢 Page_Load 工作,但支持这一点的代码非常 复杂且未针对基本场景之外的任何内容进行良好测试。 因此,如果您需要可靠性,我会坚持使用 RegisterAsyncTask。
-
This site 说:
众所周知 我们的页面生命周期有一组事件,这些事件在 预定义的顺序只有在最后一个事件发生时才会触发下一个事件 完成。所以如果我们使用上面的异步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){...}
【问题讨论】:
-
注意所有与 ASP 相关的链接都说没关系,所有非 ASP 相关的链接都说你应该非常小心你如何使用
async void。这应该告诉你一些事情,ASP 很特别。如果您阅读自己的一些链接,它们甚至会解释为什么 ASP 如此特别,以及它是如何让async void方法按您希望的方式工作的;当然,这仅适用于简单的情况;它还解释了它什么时候不起作用,以及接下来该怎么做。 -
@Servy Levi 和 Damian 在 asp.net 开发中......所以我发现很难不相信他们......但另一方面......其他原因似乎也合法......所以......:-)
标签: c# asp.net async-await .net-4.5 c#-5.0