DCSIMG
Asynchronous ASP.NET 2.0 Programming - Gady Elkarif's Blog

Gady Elkarif's Blog

Asynchronous ASP.NET 2.0 Programming

Asynchronous ASP.NET 2.0 Programming

One of the coolest features in ASP.NET 2.0 is asynchronous pages. This feature increase scalability by using thread-pool threads more efficiently.

With asynchronous pages, a thread which assigned from the thread-pool to process page request, is returned to the thread pool instead of waiting for an I/O operation to complete. This means more threads available to process incoming requests, and when I/O operation is completed, another thread from the pool is guarantee to send back the response.

There are 3 asynchronous programming model in ASP.NET 2.0:

  • Asynchronous Pages
  • Asynchronous HTTP Handlers
  • Asynchronous HTTP Modules

In this post I will cover the asynchronous pages programming model.

Asynchronous Pages in ASP.NET 2.0

Let's start by including an Async="true" attribute in the @Page directive. This tells ASP.NET to implement IHttpAsyncHandler in the page.

<%@ Page="" Async="true" Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>

AddOnPreRenderCompleteAsync

In Page_Load (or any early Page's life time) we can call to the AddOnPreRenderCompleteAsync method, to register begin and end methods, as shown in the following code:

using System;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using System.Net;

using System.IO;

 

public partial class _Default : System.Web.UI.Page

{

    private WebRequest _request;

 

    protected void Page_Load(object sender, EventArgs e)

    {

        AddOnPreRenderCompleteAsync(

            new BeginEventHandler(BeginAsyncOperation),

            new EndEventHandler(EndAsyncOperation)

        );

    }

 

    IAsyncResult BeginAsyncOperation(object sender, EventArgs e,

        AsyncCallback asyncCallback, object state)

    {

        _request = WebRequest.Create("http://blogs.microsoft.co.il/blogs/egady");

 

        return _request.BeginGetResponse(asyncCallback, state);

    }

 

    void EndAsyncOperation(IAsyncResult asyncResult)

    {

        using (WebResponse response = _request.EndGetResponse(asyncResult))

        {

            using (StreamReader reader =

                new StreamReader(response.GetResponseStream()))

            {

                string str = reader.ReadToEnd();

 

                Response.Write(str);

            }

        }

    }

}

The BeginAsyncOperation can launch an asynchronous operation such database call, or web service call, and return immediately. When this operation is completed, another thread continue from the EndAsyncOperation method to complete the request and send the response back to the client!

The result of the code is showing in the following image:

Asynchronous ASP.NET 2.0 Programming 

RegisterAsyncTask

What if you want to perform several asynchronous I/O operations in an asynchronous page which not involved remote web service/database calls? We can call AddOnPreRenderCompleteAsync multiple times, and it will cause the tasks to execute sequentially - next begin method not called until previous end method returns. For concurrent execution it will requires you to compose IAsyncResult.

The RegisterAsyncTask can helps us with this, by calling it multiple times (one per task). The tasks can be executed sequentially or concurrently, and prevent us from implementing IAsyncResult!

The following code cause to the same result like the above sample with AddOnPreRenderCompleteAsync:

using System;

using System.Collections;

using System.Configuration;

using System.Data;

using System.Linq;

using System.Web;

using System.Web.Security;

using System.Web.UI;

using System.Web.UI.HtmlControls;

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

using System.Xml.Linq;

using System.Net;

using System.IO;

 

public partial class Default2 : System.Web.UI.Page

{

    private WebRequest _request;

 

    protected void Page_Load(object sender, EventArgs e)

    {

        PageAsyncTask task = new PageAsyncTask(

            new BeginEventHandler(BeginAsyncOperation),

            new EndEventHandler(EndAsyncOperation),

            new EndEventHandler(TimeoutAsyncOperation), null

        );

        RegisterAsyncTask(task);

    }

 

    IAsyncResult BeginAsyncOperation(object sender, EventArgs e,

        AsyncCallback asyncCallback, object state)

    {

        _request = WebRequest.Create("http://blogs.microsoft.co.il/blogs/egady");

 

        return _request.BeginGetResponse(asyncCallback, state);

    }

 

    void EndAsyncOperation(IAsyncResult asyncResult)

    {

        using (WebResponse response = _request.EndGetResponse(asyncResult))

        {

            using (StreamReader reader =

                new StreamReader(response.GetResponseStream()))

            {

                string str = reader.ReadToEnd();

 

                Response.Write(str);

            }

        }

    }

 

    void TimeoutAsyncOperation(IAsyncResult asyncResult)

    {

    }

}

You can decide if the task will run in parallel or sequentially by the fifth parameter of the PageAsyncTask constructor:

  • true - Execute in parallel
  • false - Execute in series

ExecuteRegisteredAsyncTasks - Execute registered async tasks immediately, and synchronously - Please don't use this method!!

Context Flow

Another advantage of RegisterAsyncTask is that it flows request context from begin threads to end threads, and that includes:

  • HttpContext
  • Impersonation
  • Culture

While in AddOnPreRenderCompleteAsync HttpContext.Current will be null in end threads, and end threads also revert to process identity.

Conclusion

Asynchronous programming can make your application more scalable, by using the ASP.NET thread-pool more efficiently. When you take the 5-10 pages in your site, that are used mostly and have the heaviest remote I/O operations, and convert them into asynchronous pages, you can more than double your traffic into your site!

References:

kick it on DotNetKicks.com
פורסם: Sep 29 2008, 04:47 AM by egady | with 7 comment(s) |
תגים:,

תוכן התגובה

DotNetKicks.com כתב/ה:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# September 29, 2008 7:40 AM

Guy Soffer כתב/ה:

WOW, your blog is alive, cool!

# September 29, 2008 11:54 AM

alikl כתב/ה:

very good stuff - thanks for sharing!

I am working with the customer and we hitting exactly this topic. Very useful!

# September 29, 2008 3:31 PM

Mansoor Sadat כתב/ה:

Hello,

I tried the first piece of code. However, on my end I am not getting results asynchronously. I could have the definition of asynchronous wrong; from what I understand, the web page should load instantly and a process (in this case getting results from your blog page) should run in background and display results when they are available.

When I run the code above, it looks like any normal page.

Can you let me know if I am looking in the wrong place? Or, am I missing something? I do have the Async attribute in the Page directive and the rest of the code I copied and pasted into VS.

# February 7, 2009 1:19 AM

egady כתב/ה:

In client side it is synchronous, while the asynchronous behavior is only at the server side, to avoid threads from waiting to complete the request. So if you seek for asynchronously behavior in the client side, seach for AJAX technology.

# February 10, 2009 4:46 PM

Ryan_Zim כתב/ה:

Maybe you could put me in the right track, this seems to be close to what I am trying to do.

I want to have a listbox updating as a task finishes, unfortunately the postback only fires at the end of an event (the listbox only updates right at the end). I need an interactive update as a task finishes, not sure if this is possible.

Some demo coding

ListBox1.Items.Add("Finished the first item"

Threading.Thread.Sleep(1000)'This is only for 'demonstration, would be executing an sql statement 'or similar task

ListBox1.Items.Add("Finished the second item"

Threading.Thread.Sleep(1000)

ListBox1.Items.Add("Finished the third item"

Threading.Thread.Sleep(1000)

End Sub 'All three items are only refreshed or 'posted back here

# July 22, 2009 2:46 PM

Websites tagged "asynchronous" on Postsaver כתב/ה:

Pingback from  Websites tagged "asynchronous" on Postsaver

# August 1, 2009 5:17 PM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 3 and 3 and type the answer here:


Enter the numbers above: