我编写了一个自定义ASP.NET控件,我刚刚将其更新为具有异步Load事件处理程序。现在我收到了这个错误:
此时无法启动异步操作。异步操作只能在异步处理程序或模块中启动,或者在页面生命周期中的某些事件中启动。如果在执行页面时发生此异常,请确保将页面标记为<%@ Page Async =“true”%>。
页面 已经有<%@ Page Async="true" %>
标记。所以我认为控件不能有异步加载事件处理程序。
在哪里可以找到ASP.NET webforms生命周期中允许异步的事件的完整列表?
答案 0 :(得分:28)
来自ASP.NET团队的Levi Broderick给出了这个答案:Web表单中的异步void事件处理程序仅在某些情况下受支持 事件,正如你所发现的那样,但实际上只是为了简单化 任务。我们建议使用PageAsyncTask进行任何真实的异步工作 复杂性。
Web应用程序中的异步事件本身就是一种奇怪的野兽。异步 void意味着火,忘记编程模型。这适用于 Windows UI应用程序自应用程序以来一直坚持到 操作系统会杀死它,因此每当异步回调运行时都会保证 是一个可以与之交互的UI线程。在Web应用程序中 由于请求是按照定义瞬态的,因此该模型会崩溃。如果 异步回调恰好在请求完成后运行, 无法保证回调所需的数据结构 与之互动仍处于良好状态。因此为什么火和忘记 (和async void)在Web应用程序中本质上是一个坏主意。
这 说,我们做疯狂的体操,试着做一些非常简单的事情 Page_Load工作,但支持这一点的代码非常复杂 除了基本情景之外,没有经过充分测试。所以,如果你 需要可靠性我坚持使用RegisterAsyncTask。
所以我认为我的问题的答案是:“这是错误的问题。”
正确的问题是“我的ASP.NET Web窗体应用程序中应该如何异步?”答案是将此代码段插入到您的aspx代码隐藏文件中:
this.RegisterAsyncTask(new PageAsyncTask(async cancellationToken => {
var result = await SomeOperationAsync(cancellationToken);
// do something with result.
}));
同样的技巧在ASP.NET自定义控件中有效,只需使用this.Page.RegisterAsyncTask
。
答案 1 :(得分:1)
此页面解释异步页面中的生命周期事件处理与ASP.NET 2.0中的同步页面的处理不同(图2特别有用):
Wicked Code: Asynchronous Pages in ASP.NET 2.0
您也可以找到这个使用问题(它谈到相同的错误信息):