This is a mirror of official site: http://jasper-net.blogspot.com/

Avoid shooting yourself in the foot with Tasks and Async

| Thursday, September 20, 2012
Since the release of .NET 4.5, you’ve been able to use the RTM version of Async & Await. There are some things though that can lead to very weird behaviors in your applications, and a lot of confusion. Kevin (Pilchie) over at Microsoft just gave me heads up on some of these and I thought that I would share it with the rest of you!

There was a very interesting discussion around this subject in the ##roslyn channel on freenode with @ermau and @jrusbatch.

Avoid async void

When you’re doing asynchronous methods that just return void, there is no way to track when these methods are done.

Look at the following example:

class FooBar
{
    public async void Biz()
    {
        await Foo();
    }
    public Task Foo()
    {
        return Task.Factory.StartNew(() =>
        {
            Task.Delay(2000);
            Console.WriteLine("Done!");
        });
    }
}

If we create an instance of FooBar and call Biz(), there’s no way for us to wait for the task to finish. Normally we would want a reference to a Task that we could wait for to finish, but in this case we don’t! Avoid async void whenever you can.

Just change the method signature to async Task instead and you will be able to do:

var foo = new FooBar();
foo.Biz().Wait();

The only reason you want to use async void is when you have an event handler that needs to await something. Such as a Click event handler like this:

private async void MyButton_Clicked(object sender, RoutedEventArgs e)
{
    var task = Task<string>.Factory.StartNew(() =>
    {
        Thread.Sleep(2000);

        return string.Empty;
    });

    var data = await task;

    MessageBox.Show(data);
}

Never getting that second exception when awaiting multiple results?

Consider that we have two asynchronous methods that both thrown an exception (almost at the same time), like these two methods here:

public static Task<int> Foo()
{
    return Task<int>.Factory.StartNew(() => {
        throw new Exception("From Foo!");
    });
}

public static Task<int> Bar()
{
    return Task<int>.Factory.StartNew(() =>
    {
        throw new Exception("From Bar!");
    });
}

What would happen if we called the following method?

public static async Task<int> Caclulate()
{
    return await Foo() + await Bar();
}

We would indeed get an exception thrown. But we would only get One exception thrown! In fact, the only exception that we will get is the First exception being thrown.

QR: Inline image 1

Posted via email from Jasper-net

0 comments: