对于ASP.NET pages的请求需要有HTTP handler来处理,比如Page的instance。当有一个request来请求某个.aspx页面时,ASP.NET runtime会从ASP.NET thread pool中选一个thread来处理这个request, 并且在这个请求处理完成时释放这个thread。因此,如果这个 request请求的页面中的某一个Step花费了相对较长的时间,比如调用某个web service来获取数据,那么结果就是处理这个请求的thread会一直处于idle的状态,而不能处理新的请求。而之所以这个thread会处于idle的状态,是由于ASP.NET handler处理请求时采用的是同步的方式。
为了解决这个问题,在ASP.NET 1.0中可以通过实现IHTTPAsyncHandler来实现异步的方式。而在ASP.NET 2.0之后,实现异步方式变得了更加的简单了。本文就介绍两种实现异步的方法。
1. Asynchronous Pages
要将一个普通的ASP.NET页面变成一个asynchronous page,只需要在 @Page directive 设置 Async=”true” 就可以了。
<%@ Page Async="true" %>
除此之外,还需要在Page_Load事件中来注册需要完成的异步事件。在Asynchronous page中,可以通过调AddOnPreRenderCompleteAsync这个方法来注册,注册一对Begin/End的event handler。
1: AddOnPreRenderCompleteAsync(
2: new BeginEventHandler(BeginTask),
3: new EndEventHandler(EndTask));
BeginEventHandler的方法签名
IAsyncResult BeginTask(object sender, EventArgs e, AsyncCallback cb, object state)
EndEventHandler的方法签名就相对的简单了
void EndTask(IAsyncResult ar)
那么注册的异步事件是在什么时候被执行的呢?在PreRenderComplete之前,你注册了异步事件,注册的BeginEventHandler事件t会开始执行。当异步事件执行完成后,Page就会从PreRenderComplete开始,继续完成生命周期中剩下的各个事件。为了验证异步事件是否确实是在这个PreRenderComplete事件中被执行的,我们可以再 Begin/End 事件中往页面的Trace中写入信息,并打开页面的Trace,然后看输出的Track信息
如下:
aspx.page
Begin PreRender
0.000143719091709968
0.000011
aspx.page
End PreRender
0.000170049306985077
0.000026
Begin asyc: Thread=6
0.00101590747269794