Writing Asynchronous Web Pages with ASP.NET- Part 3

This is third post in the series of Writing Asynchronous Web Pages with ASP.NET. In first post, We discussed briefly about various asynchronous patterns and wrote an asynchronous web Page using APM model. In second part, we used Event-based asynchronous pattern (EAP) and discussed it with a example. Please find the links of my earlier post below.

  1. Writing Asynchronous Web Pages with ASP.NET- Part 1
  2. Writing Asynchronous Web Pages with ASP.NET- Part 2

 

In this post, we are going to use another pattern. .NET 4.0 introduced Task Parallel Library (TPL), which simplified the way to write asynchronous code. Let’s briefly understand the TPL. It provides a method (as naming convention method name ends with async) which returns a Task (or Task<TResult>) .

Task represents an asynchronous operation which contains the Result once completes. After getting the task, we can do some other activity and can keep checking the status of the Task. Once it completes, read the result from the Task.

We can provide an asynchronous method in our class that provides an async method that returns a task as

public class MyCustomClass
{
    public Task<int> ReadAsync(byte[] buffer, int offeset, int count);
}

Task actually internally uses Thread Pool and a thread is allocated to the task using thread pool to complete the task but all this complexity is hidden from the user and .NET itself lays down the required infrastructure for this.

Now, scores of classes in .NET libraries supports this pattern and we can make use of that.

.NET4.5 made our life much easier by introducing to keywords async and await which allows us to write the asynchronous code in a synchronous way. All the other required basic activities like context switching etc are taken care by the .NET framework for us. These keywords are provided over Task Parallel Library  that got introduced in .NET 4.0. Writing asynchronous activities with these keywords are highly optimized, performance oriented and make best use of TPL.

Now let’s use this pattern and write another asynchronous page. So in this examples, I am using a WCF service that returns a list of Employees and that is getting displayed on the web page. So our Page_Load method could look like

protected async void Page_Load(object sender, EventArgs e)
{
    WcfService.Service1Client client = new Service1Client();

    var customers = await client.GetEmployeesAsync();
    gdCustomers.DataSource = customers;
    gdCustomers.DataBind();
}

So as we see here that my service supports the TPL, async and await keywords based asynchronous pattern.

In page life cycle, when Page_load gets fired, ASP.NET finds it async and when it reaches to await, it releases the current thread and a new thread is picked from the thread pool to continue the activity and the call the web service took place asynchronously. Once the data returns from service, the same UI thread is assigned to execute further.
But there is better way to use async and await in web page. This has an issue as well and execute the code in synchronous mode . As we know our page life cycle has a set of events that gets fired in a predefined order and next event will be fired only when the last event completes. So if we use the above way of async Page_Load, this event will be fired during page life cycle event once it reaches to async, current thread gets free and a another thread got assigned to complete the task asynchronously, but the ASP.NET cannot execute the next event in life cycle because Page_Load has not been completed yet. And underlying synchronization context waits till the asynchronous activity completes. Then only the next event of page lifecycle will be fired which makes the whole process in synchronous mode only.

So to avoid it, there is a better is available. So the new way uses ASP.NET method RegisterAsyncTask which takes PageAsyncTask as a parameter. So let’s write the code then we’ll discuss that How does it work?

protected void Page_Load(object sender, EventArgs e)
        {
            RegisterAsyncTask(new PageAsyncTask(async () =>
            {
                using (Service1Client client = new Service1Client())
                {

                    var customers = await client.GetEmployeesAsync();
                    gdCustomers.DataSource = customers;
                    gdCustomers.DataBind();
                }
            }));
        }

Here, we have register a delegate using method RegisterAsyncTask at Page_Load. It does not fire the event while running the Page_Load event. Here it just register an event and tell the ASP.NET to execute it. Now as we have already marked page as async, ASP.NET itself decides the best time to execute it asynchronously and Page Life cycle events gets fired as usual without waiting for the async task to complete. This is very useful in the scenarios where we want to run multiple asynchronous tasks. Multiple tasks can run parallel if required. So now we have given the liberty to ASP.NET to execute this task asynchronously rather than waiting for the async task to get it completed then fire the next page life cycle events.

Hope you have enjoyed the post.

Cheers,
Brij

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s