加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – WebForms中的异步/等待 – 在页面生命周期结束之前如

发布时间:2020-12-16 03:38:07 所属栏目:asp.Net 来源:网络整理
导读:我一直在测试WebForms中的异步,一次,我的问题不是关于如何做某事,而是关于已经有效的东西,是否有效.这是我的测试代码: protected override void OnPreRender(EventArgs e){ Response.Write("OnPreRenderBr");}protected override void OnPreRenderComplete(
我一直在测试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());
}

所以我的任务暂停一点,然后写出结果.我的问题是 – 我不希望这个工作,因为控制已经从OnLoadComplete方法产生 – 我希望页面实际完成渲染并在我的任务返回之前返回到客户端.

实际输出是:

OnLoadComplete
OnPreRender
1OnPreRenderComplete

因此很明显,OnLoadComplete方法产生了控制权,以便OnPreRender可以运行,然后控制返回到OnLoadComplete.我的预期结果是“1”永远不会打印,因为随后的事件会触发,页面的线程将被杀死,或者在发送响应后发生任务后写入.我想,鉴于上述情况,即使我延迟10秒,结果也完全相同也就不足为奇了.

我假设WebForm引擎中有一些连接,确保在页面生命周期的下一阶段进行之前完成任何等待.有谁知道这是怎么发生的?我害怕在需要在其他事件之前完成的方法中使用async / await,因为担心延迟会太晚,但如果它在内部处理,那么我不会担心.

解决方法

对于ASP.NET,您应该只在.NET 4.5上使用异步方法.我会在最后解释原因.

我有an article on SynchronizationContext有助于填补关于它如何在ASP.NET上工作的空白.首先,请注意ASP.NET很久以前支持异步操作(.NET 2.0 IIRC).您可以通过几种不同的方式注册异步操作,但是对于此描述,我们将重点关注SynchronizationContext.OperationStarted.

ASP.NET为每个请求创建一个SynchronizationContext,它知道在完成所有已注册的操作之前请求未完成(通过调用SynchronizationContext.OperationCompleted). Event-based asynchronous pattern components(例如BackgroundWorker)将在启动和完成时自动通知SynchronizationContext.

同样,async void方法(新的task-based asynchronous pattern)将在启动和完成时自动通知SynchronizationContext.因此,当您将OnLoadComplete作为async void方法重写时,编译器会为您插入代码,该代码将在开始时调用OperationStarted,在完成时调用OperationCompleted.

到目前为止一直很好 – ASP.NET现在知道在请求的所有异步操作完成之前保持请求保持活动状态.即使没有处理请求的线程也是如此.

现在需要注意的是:.NET 4.5之前的ASP.NET会在请求级别处理它.在ASP.NET 4.5中,生命周期管道变得更加智能,因此它会延迟页面生命周期,直到异步操作完成.使用旧的ASP.NET,“预”处理程序将从管道中的那一点开始,但可能要到晚些时候才能完成.新的ASP.NET将延迟页面执行的其余部分,以确保在生命周期中继续之前完成异步处理程序.

此外,ASP.NET 4.5将检测您是否使用了不应该有异步处理程序的异步处理程序,并将通知您该错误.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读