The Task-based Asynchronous Pattern - Part 1 (The Basics)

October 31, 2010 | Async

The future of asynchronous programming in C# adheres to a new language feature and a new framework pattern. 

Asynchronous programming will be similar to synchronous programming.

Today hosting in the cloud has become popular. You’re paying for each virtual machine (VM) that is running so your service must scale or else you have to pay for another VM to handle the load.  Both the classic APM and the EAP require you to split your code in a callback function so many people even chose to write their code synchronous. No matter if you call a web service or access a file on disk (that is, I/O-Bound Asynchronous Operations) or if you want to compute PI (a Periodic Compute-Bound Operation) your application has to be scalable and responsive.    

I have already discussed about the two patterns that are available in the .NET Framework for asynchronous programming.

I like the APM because with a good IAsyncResult implementation in hand you can easily expose asynchronous features to all versions of the .NET Framework (1.0-today) and also target Microsoft Silverlight, Windows Phone 7, etc. 

To start, here is some code that executes synchronously:

private void FetchStockQuotesSync(WebService svc)
{
    // This blocks. You don't know when the FetchStockQuotes
    // method returns. It may takes from minutes, to hours or
    // it may not return at all.
    IStockQuote qt = svc.FetchStockQuotes();
}

Fortunately the WebService class implements the IAsyncResult interface, so the same code can be executed asynchronously:

private void FetchStockQuotesApm(WebService svc)
{
    // This never blocks. Your code returns immediately.
    svc.BeginFetchStockQuotes(FetchStockQuotesApmCallback, svc);
}

private void FetchStockQuotesApmCallback(IAsyncResult ar)
{
    // The operation completed asynchrnously.
    WebService svc = (WebService)ar.AsyncState;
    IStockQuote qt = svc.EndFetchStockQuotes(ar);
}

Event if the WebService class does not implement the IAsyncResult interface, you can define a delegate and invoke it asynchronously, via BeginInvoke.

The following code below is here just for the demo. There is a known performance hit when calling delegates compared to direct method calls. (See the Delegates section here).

private void FetchStockQuotesApm(WebService svc)
{
    // This never blocks. Your code returns immediately.
    Func<IStockQuote> @delegate = svc.FetchStockQuotes;
    @delegate.BeginInvoke(FetchStockQuotesApmCallback, @delegate);
}

private void FetchStockQuotesApmCallback(IAsyncResult ar)
{
    // The operation completed asynchrnously.
    Func<IStockQuote> @delegate = (Func<IStockQuote>)ar.AsyncState;
    IStockQuote qt  = @delegate.EndInvoke(ar);
}

Unfortunately, it turns out that the APM does not look so sexy and most of the developers just don't use it. 

The future of asynchronous programming in C# adheres to a new framework pattern called the Task-based Asynchronous Pattern (TAP).

The new language features async and await and the TAP allow you to do this:

private async void FetchStockQuotesAsyncCtp(WebService svc)
{
    IStockQuote qt = await svc.FetchStockQuotesTaskAsync();
}

Well, this is exciting.  The method is marked as async. This means that the method body is compiled specially, allowing parts of it to be turned into callbacks. The FetchStockQuotesTaskAsync method returns a Task<IStockQuote> by converting the BeginFetchStockQuotes/EndFetchStockQuotes methods into a task. Until the task completes, there is nothing to do but await for it.

Here is how the FetchStockQuotesTaskAsync method is written:

public static Task<IStockQuote> FetchStockQuotesTaskAsync(this IWebService svc)
{
    return Task<IStockQuote>.Factory.FromAsync(
        svc.BeginFetchStockQuotes, // BeginPart
        svc.EndFetchStockQuotes,   // EndPart
        null);                     // State, Options
}

FetchStockQuotesTaskAsync is an extension method, because adding this feature directly to the WebService class will break compatibility with previous versions of the .NET Framework (1.0, 1.1, 2.0). Also, if you don't own the code of the WebService class you would define it as an extension method anyway.

It becomes very clear that in the near future it's the programming language that will handle most of the asynchronous stuff and not the programmer. Currently, you can download and install the Async CTP. For more information around the new features you can visit the official website here.

The sample application can be found here.