Visual Studio Async CTP: A Few More Things

October 28, 2010

no comments

I gave a couple of examples in my previous post which demonstrate, IMHO, how async methods can simplify existing approaches to asynchrony in C# programs. Both examples were fairly simple in that they didn’t involve cancellation, progress reporting, UI thread dispatching, or exception handling.

I’m happy to report that accomplishing these objectives is as easy as doing nothing else than what we’ve already seen.

This is a result of a fairly sophisticated C# rewriting process that the compiler applies to async methods, not unlike the rewriting process applied to iterator blocks (“yield return” and “yield break”). For example, the following async method:

static async void M() {
    S();        //synchronous part
    await T();  //queue continuation
    C();        //continuation
}

Is compiled to the following C# code, according to Reflector:

private static void M()
{
    <M>d__2f d__f = new <M>d__2f(0);
    d__f.MoveNextDelegate = new Action(d__f.MoveNext);
    d__f.$builder = VoidAsyncMethodBuilder.Create();
    d__f.MoveNext();
}
[CompilerGenerated]
private sealed class <M>d__2f
{
    //…snipped for brevity
    public void MoveNext()
    {
        try
        {
            this.$__doFinallyBodies = true;
            if (this.<>1__state != 1)
            {
                if (this.<>1__state == -1)
                {
                    return;
                }
                Program.S();
                this.<a1>t__$await30 =
                    Program.T().GetAwaiter();
                this.<>1__state = 1;
                this.$__doFinallyBodies = false;
                if (this.<a1>t__$await30.BeginAwait(
                    this.MoveNextDelegate))
                {
                    return;
                }
                this.$__doFinallyBodies = true;
            }
            this.<>1__state = 0;
            this.<a1>t__$await30.EndAwait();
            Program.C();
            this.<>1__state = -1;
            this.$builder.SetCompleted();
        }
        catch (Exception)
        {
            this.<>1__state = -1;
            this.$builder.SetCompleted();
            throw;
        }
    }
}

This rewriting process takes into consideration also exception handling. In other words, your async methods can wrap code in try…catch blocks just like their synchronous counterparts; exceptions that arise in one of the awaited tasks, in the synchronous section of the code, or in one of the continuations, are all propagated into the respective exception handling blocks. For example:

async void WithExceptions()
{
    try
    {
        //An exception that arises here (e.g. in the
        //synchronous part of DownloadDataTaskAsync),
        //or in the continuation, will be caught by
        //the catch block below.
        var t = new WebClient().DownloadDataTaskAsync(
            "http://www.microsoft.com");
        if (t !=
            await TaskEx.WhenAny(t, TaskEx.Delay(100)))
        {
            throw new TimeoutException();
        }
    }
    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

Similarly, cancellation takes an approach familiar from .NET 4.0 APIs such as Parallel.For or Task.StartNew. You can pass a CancellationToken into any async method that accepts one, and that async method can rendezvous with the token by using CancellationToken.ThrowIfCancellationRequested or any other method.

Similarly, while you’re using cancellation, you’ll notice a new extension method, CancellationTokenSource.CancelAfter. This is a really simple method to write, and it automagically cancels the operation after the specified timeout has elapsed. You could implement it with a timer, like the CTP does; or you could:

async void CancelAfter(
    this CancellationTokenSource cts, int timeout)
{
    await TaskEx.Delay(timeout);
    try { cts.Cancel(); }
    catch (ObjectDisposedException) { }
}

I’ll leave it to you now to download the Visual Studio Async CTP and its accompanying documentation, to watch Anders Hejlsberg’s PDC session, and to get your own impression whether this is a feature that’s going to make your asynchronous programs easier to write and easier to read.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*