Win the Waiting Game with ASP.NET Asynchronous Pages

ASP.NET 2.0 provides an easy-to-use API for keeping your apps from stalling on I/O-bound operations


April 25, 2006
URL:http://drdobbs.com/windows/win-the-waiting-game-with-aspnet-asynchr/186700817

Certain behaviors that ASP.NET pages implement might rely on potentially lengthy functions, such as a web service call. In these cases, the classic and inherently synchronous processing model of ASP.NET pages is simply unfit. Asynchronous HTTP handlers have existed since ASP.NET 1.0; but only ASP.NET 2.0 provides specific support for asynchronous pages and a surprisingly easy-to-use API. Each new request coming to the application is served by a selected HTTP handler. The thread calls a particular method on the handler (named ProcessRequest) and waits for it to terminate. The question is, for how long?

If the operation completes slowly for whatever reason, a "synchronous" ASP.NET page is blocked, and so is the underlying thread. Using synchronous handlers for potentially long, non-CPU-bound operations puts application scalability at serious risk. An "asynchronous" page would divide execution in two parts-when the operation is begun and when it has terminated. These two segments of execution typically occur different threads and clearly at different times. Let's see how to create asynchronous pages in ASP.NET 2.0.

Two aspects characterize an asynchronous ASP.NET page: a new attribute on the @Page directive, and one or more tasks registered for asynchronous execution. The asynchronous task is registered through a Begin/End pair of asynchronous handlers for the PreRenderComplete event.

The page can wire up asynchronously to the PreRenderComplete event at any time in the life cycle, provided that it happens before the PreRender event fires. This is generally done in the Page_Load event, and the process consists of a call to the new method AddOnPreRenderCompleteAsync defined on the Page class.

 AddOnPreRenderCompleteAsync (
    new BeginEventHandler(BeginTask),
    new EndEventHandler(EndTask)
 );
The BeginEventHandler and EndEventHandler are delegates defined as follows:

 IAsyncResult BeginEventHandler(
    object sender,
    EventArgs e, 
    AsyncCallback cb, 
    object state)
 void EndEventHandler(
    IAsyncResult ar)
 
A good place in the code file where you can place a call to AddOnPreRenderCompleteAsync is usually the Page_Load event.

The Begin handler is responsible for starting any long operation. The handler is expected to return an IAsyncResult object to describe the state of the asynchronous task. The End handler completes the operation and updates the page's user interface and controls. Note that you don't necessarily have to create your own object that implements the IAsyncResult interface. In most cases, in fact, to start lengthy operations you just use .NET built-in classes that already implement the asynchronous pattern and provide IAsyncResult ready-made objects.

The invocation of aforementioned handlers is related to a flag that clearly indicates the page is asynchronous. The new Async attribute on the @Page directive accepts a Boolean value to enable or disable asynchronous processing. The default value is false.

 <%@ Page Async="true" ... %>
 

The attribute is merely a message for the page parser. When the attribute is set, the page parser implements the IHttpAsyncHandler interface (instead of IHttpHandler) in the dynamically generated class for the .aspx resource. The Async attribute enables the page to register asynchronous handlers for the PreRenderComplete event. No additional code is executed at run time as a result of the attribute.

Which operations are good candidates to be implemented in asynchronous pages? Any operation can be roughly labeled in either of two ways: CPU bound or I/O bound. CPU bound indicates an operation whose completion time is mostly determined by the speed of the processor and amount of available memory. I/O bound indicates the opposite situation, where the CPU mostly waits for other devices to terminate. From this description, it is clear that I/O bound are excellent candidates to async execution because they rely on external resources and leave the CPU free to serve more requests and maintain (if not increase) the level of scalability.

<

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.