C# 5 Async, Part 3: Preparing Existing code For Await

While the Visual Studio Async CTP provides a fantastic model for asynchronous programming, it requires code to be implemented in terms of Task and Task<T>.  The CTP adds support for Task-based asynchrony to the .NET Framework methods, and promises to have these implemented directly in the framework in the future.  However, existing code outside the framework will need to be converted to using the Task class prior to being usable via the CTP.

Wrapping existing asynchronous code into a Task or Task<T> is, thankfully, fairly straightforward.  There are two main approaches to this.

Code written using the Asynchronous Programming Model (APM) is very easy to convert to using Task<T>.  The TaskFactory class provides the tools to directly convert APM code into a method returning a Task<T>.  This is done via the FromAsync method.  This method takes the BeginOperation and EndOperation methods, as well as any parameters and state objects as arguments, and returns a Task<T> directly.

For example, we could easily convert the WebRequest BeginGetResponse and EndGetResponse methods into a method which returns a Task<WebResponse> via:

Task<WebResponse> task = Task.Factory
                             .FromAsync<WebResponse>(
                                 request.BeginGetResponse,
                                 request.EndGetResponse,
                                 null);

Event-based Asynchronous Pattern (EAP) code can also be wrapped into a Task<T>, though this requires a bit more effort than the one line of code above.  This is handled via the TaskCompletionSource<T> class.  MSDN provides a detailed example of using this to wrap an EAP operation into a method returning Task<T>.  It demonstrates handling cancellation and exception handling as well as the basic operation of the asynchronous method itself.

The basic form of this operation is typically:

Task<YourResult> GetResultAsync()
{
    var tcs = new TaskCompletionSource<YourResult>();
    // Handle the event, and setup the task results...
    this.GetResultCompleted += (o,e) =>
    {
       if (e.Error != null)
            tcs.TrySetException(e.Error);
       else if (e.Cancelled)
            tcs.TrySetCanceled();
       else
            tcs.TrySetResult(e.Result);
    };

    // Call the EAP-based asynchronous method
    this.GetResult();

    // Return the task from the TaskCompletionSource
    return tcs.Task;
}

We can easily use these methods to wrap our own code into a method that returns a Task<T>.  Existing libraries which cannot be edited can be extended via Extension methods.  The CTP uses this technique to add appropriate methods throughout the framework.

The suggested naming for these methods is to define these methods as “Task<YourResult> YourClass.YourOperationAsync(…)”.  However, this naming often conflicts with the default naming of the EAP.  If this is the case, the CTP has standardized on using “Task<YourResult> YourClass.YourOperationTaskAsync(…)”.

Once we’ve wrapped all of our existing code into operations that return Task<T>, we can begin investigating how the Async CTP can be used with our own code.

About Reed
Reed Copsey, Jr. - http://www.reedcopsey.com - http://twitter.com/ReedCopsey

Comments

4 Responses to “C# 5 Async, Part 3: Preparing Existing code For Await”
  1. Hello Reed,
    Why have you tagged your C# 5 articlles with “C# 4″ tag?

    (I am interested to find and run code in C# 4 but not C# 5)

  2. tim says:

    Hi, I tried your basic form and it works with one caveat. For some reason, when I call it with “await” it never waits. The only way I could get it to work is to sneak in tcs.Task.Wait() which obviously defeats the purpose. Any idea what could be going wrong?

Speak Your Mind

Tell us what you're thinking...
and oh, if you want a pic to show with your comment, go get a gravatar!