I’ve been going to Microsoft’s Professional Developer’s Conference (PDC) for over a decade now and one thing that I’ve learnt over that time is;

1. The Anders Heijlsberg talk is the talk that everyone wants to see

2. The Anders Heijlsberg talk is the talk that you won’t get into as a Microsoft employee because the room will be full ( see point (1) above Smile )

Last year’s mini-PDC in Seattle was no exception as Anders showed up and talked about future changes coming to both C# and VB in the area of asynchronous programming.

You can still watch the talk today on Channel9.

There’s a preview of this work available as the “Visual Studio 2010 Async CTP” and this was refreshed for Visual Studio 2010 Sp1 just a few weeks ago.

Asynchronous programming seems to be coming more and more to the fore. Perhaps it’s because users are tired of client side applications that are unresponsive or hang. Perhaps it’s because we’re trying to squeeze more and more out of server-side environments and so don’t want to tie up threads while we’re waiting for database or service calls to complete.

Perhaps it’s just that everything’s so much more connected than it used to be and older techniques of trying to pretend the network is transparent and synchronous when it’s neither just don’t work today.

Whatever the reasons though, asynchronous code is everywhere and asynchronous code is hard.

Imagine that I want to do something as “simple” as perform 3 concurrent web requests to some websites and determine the length of the response stream returned.

Here’s my first attempt;

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
 
class Program
{
  static void Main(string[] args)
  {
    string[] websiteUrls = 
      {
        "http://www.microsoft.com",
        "http://www.apple.com",
        "http://www.oracle.com"
      };
 
    List<Exception> exceptions = new List<Exception>();
    ManualResetEvent doneEvent = new ManualResetEvent(false);
    int outstandingItemCount = websiteUrls.Length;
 
    foreach (var url in websiteUrls)
    {
      WebRequest request = WebRequest.Create(url);
 
      request.BeginGetResponse(
        result =>
        {
          try
          {
            WebResponse response = request.EndGetResponse(result);
 
            using (Stream stream = response.GetResponseStream())
            {
              using (StreamReader reader = new StreamReader(stream))
              {
                int contentLength = reader.ReadToEnd().Length;
 
                Console.WriteLine("Website [{0}] length [{1}]",
                  response.ResponseUri, contentLength);
              }
              stream.Close();
            }
          }
          catch (Exception ex) // catching too much here.
          {
            lock (exceptions)
            {
              exceptions.Add(ex);
            }
          }
          finally
          {
            if (Interlocked.Decrement(ref outstandingItemCount) == 0)
            {
              doneEvent.Set();
            }
          }
        }, null);
    }
    Console.WriteLine("Waiting...");
    doneEvent.Set();
    Console.WriteLine("Done...");
    Console.WriteLine("Encountered [{0}] exceptions", exceptions.Count);
    Console.ReadLine();
  }
}

I’m not 100% confident that it’s correct as I didn’t spend a tonne of time on it but then I didn’t really expect to – it’s a fairly simple thing to want to do and yet it seems so hard. The savvy reader might also notice that I didn’t even attempt to read the data from the network streams asynchronously as it would make my code snippet even longer and harder.

The new asynchronous programming support that previews in the Async CTP is about trying to make this a whole lot easier and it builds on the Task Parallel Library (TPL) that was added to .NET in V4.0. You can read more about Tasks here on MSDN.

Let’s say that I start with something a little simpler and just wanted to write a function that performs one asynchronous download and returns the response Stream;

  static async Task<Stream> AsynchronousDownload(string url)
  {
    WebRequest request = WebRequest.Create(url);
 
    WebResponse response = await request.GetResponseAsync();
 
    return (response.GetResponseStream());
  }

There’s a lot of mystery going on in what looks like a simple 3-line function. Firstly, the modifier async signifies to the compiler that this isn’t just a regular function and it will force the function to return either a Task, a Task<T> or void.

The return type of Task<Stream> means that this function represents a piece of work which may in the future return a Stream and that Task<T> has a lot of functionality including methods/properties such as;

  • Result (of type Stream in our case and the property accessor blocks if the result is not yet available)
  • Exception (which is of type AggregateException and so can include many Exceptions that might be raised by work undertaken by sub-Tasks)
  • IsCompleted/IsCanceled/IsFaulted by which we can work out what the result was when it happened
  • Wait() which can be used to wait for the Task to complete (or fail, or be cancelled)

Because of the async modifier, the compiler will also “expect” that the function will await at least once in its operation but it doesn’t have to – if there are no such awaits then the compiler issues a warning that the function will execute synchronously.

The calls to await logically represent points at which the synchronous execution of the function can “return” to the caller returning back an instance of Task which is potentially incomplete at that point but can then be waited on for completion.

Whatever operation has been awaited will later complete and the flow of execution will logically continue at the point of the await call albeit potentially on a different thread than the one which “began” the execution of the function.

In this particular case, we await a call to WebRequest.GetResponseAsync() which is mainly interesting because it doesn’t exist Smile

This is a piece of magic – the compiler can only await operations that have a certain “awaitable” pattern and a WebRequest does not fulfil that pattern. However, the Async CTP brings in an extension method WebRequest.GetResponseAsync() which brings it into line with the pattern.

How can this function that we’ve written be used? Easy;

    Task<Stream> download = AsynchronousDownload("http://www.microsoft.com");
    download.Wait();
 
    if (download.IsCompleted)
    {
      using (Stream stream = download.Result)
      {
        stream.Close();
      }
    }
    else if (download.IsFaulted)
    {
      AggregateException exceptions = download.Exception;
    }

Where this perhaps gets more interesting is in how this function can now be used within another asynchronous function such as this one which does a number of asynchronous downloads;

  static async Task AsynchronousDownload(string[] urls)
  {
    foreach (var url in urls)
    {
      using (Stream stream = await AsynchronousDownload(url))
      {        
        using (StreamReader reader = new StreamReader(stream))
        {
          int contentLength = reader.ReadToEnd().Length;
 
          Console.WriteLine("Website [{0}] length [{1}]",
            url, contentLength);
        }
        stream.Close();
      }
    }
  }

Effectively, we’ve now composed one asynchronous method within another and we’ve suffered almost no pain for it and the code is so much neater than where it started. The complete code is now at this stage;

using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
 
class Program
{
  static async Task<Stream> AsynchronousDownload(string url)
  {
    WebRequest request = WebRequest.Create(url);
 
    WebResponse response = await request.GetResponseAsync();
 
    return (response.GetResponseStream());
  }
  static async Task AsynchronousDownload(string[] urls)
  {
    foreach (var url in urls)
    {
      using (Stream stream = await AsynchronousDownload(url))
      {        
        using (StreamReader reader = new StreamReader(stream))
        {
          int contentLength = reader.ReadToEnd().Length;
 
          Console.WriteLine("Website [{0}] length [{1}]",
            url, contentLength);
        }
        stream.Close();
      }
    }
  }
  static void Main(string[] args)
  {
    string[] websiteUrls = 
      {
        "http://www.microsoft.com",
        "http://www.apple.com",
        "http://www.oracle.com"
      };
 
    Console.WriteLine("Waiting...");
    Task task = AsynchronousDownload(websiteUrls);
    task.Wait();
    Console.WriteLine("Done...");
 
    // tbd - not sure I've used Flatten() correctly here.
    Console.WriteLine("Encountered [{0}] exceptions",
      task.IsFaulted ? task.Exception.Flatten().InnerExceptions.Count : 0);
 
    Console.ReadLine();
  }
}

Compared to the original example, this is a thing of rare beauty and elegance Smile but it’s fair to say that it’s not quite doing the same thing. This new code performs each asynchronous HTTP GET after the previous one thereby chaining them whereas the first example did them in parallel. Can we get back to that without sacrificing the programming model?

There’s a number of ways of achieving this but I think the one that makes the most sense here is to refactor things a little;

using System;
using System.Collections.Concurrent;
using System.IO;
using System.Net;
using System.Threading.Tasks;
 
class Program
{
  // Refactored so that it does both the work of the download and
  // the work of writing the results to the console.
  static async Task AsynchronousDownload(string url)
  {
    WebRequest request = WebRequest.Create(url);
 
    WebResponse response = await request.GetResponseAsync();
 
    using (Stream stream = response.GetResponseStream())
    {
      using (StreamReader reader = new StreamReader(stream))
      {
        int contentLength = reader.ReadToEnd().Length;
 
        Console.WriteLine("Website [{0}] length [{1}]",
          url, contentLength);
      }
      stream.Close();
    }
  }
  // Refactored so that it starts all the tasks together and
  // waits for them all to complete
  static async Task AsynchronousDownload(string[] urls)
  {
    ConcurrentBag<Task> tasks = new ConcurrentBag<Task>();
 
    foreach (var url in urls)
    {
      Task task = AsynchronousDownload(url);
 
      tasks.Add(task);
    }
    await TaskEx.WhenAll(tasks);
  }
  static void Main(string[] args)
  {
    string[] websiteUrls = 
      {
        "http://www.microsoft.com",
        "http://www.apple.com",
        "http://www.dell.com"
      };
 
    Console.WriteLine("Waiting...");
    Task task = AsynchronousDownload(websiteUrls);
    task.Wait();
    Console.WriteLine("Done...");
 
    // tbd - not sure I've used Flatten() correctly here.
    Console.WriteLine("Encountered [{0}] exceptions",
      task.IsFaulted ? task.Exception.Flatten().InnerExceptions.Count : 0);
 
    Console.ReadLine();
  }
}

In this final version of the program, we’ve changed the nature of the work slightly such that all asynchronous downloads can be started at once and then waited for as a single unit of work.

It’s debatable as to whether the second AsynchronousDownload(string[]) method here really needs to be marked as async and use an await because it does not do any work after waiting for all of the sub-tasks to complete. However, the use of await with TaskEx.WaitAll() does make it easy to implicitly return a Task to the caller.

There’s great work going on in the Asynchronous CTP. If you’ve not had a chance to experiment with it then I’d encourage you to take a look, read through some of the documentation and perhaps try out some of the samples.

If you’re on versions of .NET prior to 4 or are just coming to 4 with Visual Studio 2010 then I’d also encourage you to take a good look at the Task class and the Task Parallel Library in general as they are becoming the building blocks for what’s coming down the line.