Turn IAsyncResult code into the new async and await Keyword Pattern


C# is one of those beautiful languages which seems to evolve into the most gracious programming languages. With the introductions of the await and async keywords introduced in C# 5.0, parallel programming just got a lot easier. It builds the language feature on top of the excellent System.Threading.Tasks namespace implemented from .NET 4.0+ versions.

To compliment the new await keyword, the .NET 4.5 framework ships with additional methods named xxxAsync. For reasons beyond the scope of this blog post, these new xxxAsync methods will return a Task or Task<TResult>. The BCL team did an excellent job of implementing methods like these on the very commonly used classes which would benefit from parallel programming, such as the FileStream.

// Sample extracted from: http://msdn.microsoft.com/en-us/library/kztecsys.aspx
string StartDirectory = @"c:\Users\exampleuser\start";
string EndDirectory = @"c:\Users\exampleuser\end";

foreach (string filename in Directory.EnumerateFiles(StartDirectory))
{
    using (FileStream SourceStream = File.Open(filename, FileMode.Open))
    {
        using (FileStream DestinationStream = File.Create(EndDirectory + filename.Substring(filename.LastIndexOf('\\'))))
        {
            await SourceStream.CopyToAsync(DestinationStream);
        }
    }
}

However, not all the classical IAsyncResult has an equivalent xxxAsync method which returns a Task or Task<TResult>. One such example is the raw Socket class - using the await pattern on such a class would definitely assist bringing down the bug count since the programmer does not have to manage the delicate callback mechanisms.

The good news is that there is a provision to convert those IAsyncCallback “contracts” into “awaitable” code. They can be wrapped by following methods.

  • TaskFactory.FromAsync overloads.
  • TaskFactory<TResult>.FromAsync overloads.

An example usage of the two methods:

// TaskFactory.FromAsync
await Task.Factory.FromAsync(
    rawSocket.BeginConnect,                 // (1)
    rawSocket.EndConnect,                   // (2)
    parameter1_hostName, parameter2_port, null);
    
// and the TaskFactory<TResult>.FromAsync
Socket clientSocket = await Task<Socket>.Factory.FromAsync(serverSocket.BeginAccept,
                                                           serverSocket.EndAccept,
                                                           null);

There are a couple of notes in the above code illustrations.

  1. If the beginMethod delegate accepts parameters (commented with “(1)”), it elegantly accepts the parameter values latter on after the endMethod parameter (commented with “(2)”). At least you do not have to write wrapping anonymous delegates.

  2. I used the default TaskFactory on the Task and Task<TResult> because there is not a good reason to have a seperate scheduler for your TPL code.

So, there it is: an elegant way to wrap those classical IAsyncCallback code into the cool awaitable code, even in the absence of the baked in xxxAsync methods.

blog comments powered by Disqus