当前位置导航:炫浪网>>网络学院>>网页制作>>ASP.NET教程

ASP.NET 2.0 中的异步页功能应用

ASP.NET 2.0 提供了大量新功能,其中包括声明性数据绑定和母版页,成员和角色管理服务等。但我认为最棒的功能是异步页,接下来让我告诉您其中的原因。

  当 ASP.NET 接收针对页的请求时,它从线程池中提取一个线程并将请求分配给该线程。一个普通的(或同步的)页在该请求期间保留线程,从而防止该线程用于处理其他请求。如果一个同步请求成为 I/O 绑定(例如,如果它调用一个远程 Web 服务或查询一个远程数据库,并等待调用返回),那么分配给该请求的线程在调用返回之前处于挂起状态。这影响了可伸缩性,原因是线程池的可用线程是有限的。如果所有请求处理线程全部阻塞以等待 I/O 操作完成,则其他请求排入队列等待线程释放。最好的情况是吞吐量减少,因为请求等待较长的时间才能得到处理。最坏的情况则是该队列填满,并且 ASP.NET 因 503“Server Unavailable”错误使后续请求失败。

  异步页为由 I/O 绑定的请求引起的问题提供优秀的解决方案。页处理从线程池线程开始,但是当一个异步 I/O 操作开始响应 ASP.NET 的信号之后,该线程返回线程池。当该操作完成时,ASP.NET 从线程池提取另一个线程,并完成该请求的处理。由于线程池线程得到了更高效的使用,因此提高了可伸缩性。那些挂起等待 I/O 完成的线程现在可用于服务其他请求。直接的受益方是不执行长时间 I/O 操作并因此可以快速进出管线的请求。长时间等待进入管线会对此类请求的性能带来不小的负面影响。

  ASP.NET 2.0 Beta 2 异步页基础结构的相关文档很少。让我们展望一下异步页的前景,从而弥补这点不足。请记住,本专栏涉及 ASP.NET 2.0 和 .NET Framework 2.0 的测试版本。

 ASP.NET 1.x 中的异步页

  ASP.NET 1.x 本质上不支持异步页,但是通过坚韧的努力和不懈地创新可以生成异步页。有关更多概述信息,请参阅相关资料

  这里的技巧是,在一个页的代码隐藏类中实现 IhttpAsyncHandler,从而提示 ASP.NET 通过调用 IHttpAsyncHandler.BeginProcessRequest 来处理请求,而不是通过调用该页的 IHttpHandler.ProcessRequest 方法。然后,您的 BeginProcessRequest 实现可以启动另一个线程。该线程调用 base.ProcessRequest,使得页进入其常规请求处理生命周期(完成诸如 Load 和 Render 的事件),但是在非 ThreadPool 线程上例外。同时,启动新线程之后 BeginProcessRequest 立即返回,从而允许执行 BeginProcessRequest 的线程返回线程池。

  这是基本思想,但细节中还有很多注意事项。其中,您需要实现 IAsyncResult,并从 BeginProcessRequest 中返回它。这通常意味着创建一个 ManualResetEvent 对象,并且当 ProcessRequest 在后台线程中返回时向其发送信号。此外,您必须提供调用 base.ProcessRequest 的线程。遗憾的是,多数用于将工作移到后台线程的常规技术(包括 Thread.Start、ThreadPool.QueueUserWorkItem 和异步委托)在 ASP.NET 应用程序中都是起反作用的,因为它们或者从线程池“偷盗”线程,或者有不受限制的线程增长的危险。正确的异步页实现使用自定义线程池,但自定义线程池类不容易编写。

  主要是在 ASP.NET 1.x 中生成异步页并非不可能,而是有些乏味。在尝试一、两次之后,您不禁会想一定会有更好的方法。目前,这个好方法就是 ASP.NET 2.0。

 ASP.NET 2.0 中的异步页

  ASP.NET 2.0 极大地简化了生成异步页的方式。首先使用该页的 @ Page 指令引入 Async=“true” 属性,如下所示:

  在后台,这会通知 ASP.NET 在该页中实现 IhttpAsyncHandler。接下来,您在该页生存期的早期(例如,在 Page_Load 时)调用新的 Page.AddOnPreRenderCompleteAsync 方法来注册一个 Begin 方法和一个 End 方法,

共2页 首页 上一页 1 2 下一页 尾页 跳转到
相关内容
赞助商链接