pow*_*tte 5 asp.net webforms async-await
我一直在测试WebForms中的异步,一次,我的问题不是关于如何做某事,而是关于已经有效的东西,是否有效.这是我的测试代码:
protected override void OnPreRender(EventArgs e)
{
Response.Write("OnPreRender<Br>");
}
protected override void OnPreRenderComplete(EventArgs e)
{
Response.Write("OnPreRenderComplete<Br>");
}
protected async override void OnLoadComplete(EventArgs e)
{
Response.Write("OnLoadComplete<br>");
var t1 = Task.Factory.StartNew(() => {
System.Threading.Thread.Sleep(2000);
return 1;
});
//This actually does run:
Response.Write((await t1).ToString());
}
Run Code Online (Sandbox Code Playgroud)
所以我的任务暂停一点,然后写出结果.我的问题是 - 我不希望这个工作,因为控制已经从OnLoadComplete方法产生 - 我希望页面实际完成渲染并在我的任务返回之前返回到客户端.
实际输出是:
OnLoadComplete
OnPreRender
1OnPreRenderComplete
Run Code Online (Sandbox Code Playgroud)
因此很明显,OnLoadComplete方法产生了控制权,以便OnPreRender可以运行,然后控制返回到OnLoadComplete.我的预期结果是"1"永远不会打印,因为随后的事件会触发,页面的线程将被杀死,或者在发送响应后发生任务后写入.我想,鉴于上述情况,即使我延迟10秒,结果也完全相同也就不足为奇了.
我假设WebForm引擎中有一些连接,确保在页面生命周期的下一阶段进行之前完成任何等待.有谁知道这是怎么发生的?我害怕在需要在其他事件之前完成的方法中使用async/await,因为担心延迟会太晚,但如果它在内部处理,那么我不会担心.
Ste*_*ary 11
对于ASP.NET,您应该只async在.NET 4.5上使用方法.我会在最后解释原因.
我有一篇文章SynchronizationContext有助于填补有关ASP.NET如何工作的空白.首先,请注意ASP.NET很久以前支持异步操作(.NET 2.0 IIRC).您可以通过几种不同的方式注册异步操作,但是对于此描述,我们将重点关注SynchronizationContext.OperationStarted.
ASP.NET SynchronizationContext为每个请求创建一个,并且在完成所有已注册的操作(通过调用SynchronizationContext.OperationCompleted)之前,它知道请求未完成.基于事件的异步模式组件(如BackgroundWorker)将SynchronizationContext在启动和完成时自动通知.
同样,async void方法(基于任务的新异步模式)将SynchronizationContext在启动和完成时自动通知.因此,当您OnLoadComplete作为async void方法覆盖时,编译器会为您插入代码,该代码将OperationStarted在开头和OperationCompleted完成时调用.
到目前为止一直很好 - ASP.NET现在知道在请求的所有异步操作完成之前保持请求保持活动状态.即使没有处理请求的线程也是如此.
现在需要注意的是:.NET 4.5之前的ASP.NET会在请求级别处理它.在ASP.NET 4.5中,生命周期管道变得更加智能,因此它会延迟页面生命周期,直到异步操作完成.使用旧的ASP.NET,"预"处理程序将从管道中的那一点开始,但可能要到晚些时候才能完成.新的ASP.NET将延迟页面执行的其余部分,以确保async处理程序在生命周期中继续之前完成.
此外,ASP.NET 4.5将检测您是否使用了async不应该有处理程序的处理程序,并将通知您错误.
| 归档时间: |
|
| 查看次数: |
2811 次 |
| 最近记录: |