Where worlds collide

At work, we came across one of those interesting situations where two different abstractions look at the same type in different ways, making things fine if you view the type through one abstraction, but confusing it you know about both.

There was a piece of code that started a task that threw an exception – obviously it was more complicated than this, but it gives the idea:
    Task<int> t = Task.Run<int>((Func<int>)delegate { throw new ArgumentException(); });

And a piece of code that started this and caught the exception.
  try
{
    var a = t.Result;  
}
catch (AggregateException)
{
     // …
}

Note that we need to catch AggregateException. The TPL offers some operations on tasks that can raise multiple exceptions. AggregateException is a wrapper that allows multiple exceptions to be returned.

Now using the modern C# 5 async abstraction, we might change the code to
  var a = await t;

The whole async mechanism is built on top of tasks, but it tries to keep the manipulation of Tasks out of the picture. It would therefore be confusing to the users if they needed to catch AggregateException around any calls to await. Hence the TaskAwaiter, which comes into the picture because
  await t
is essentially translated to
  t.GetAwaiter().GetResult()
looks at the Task and takes only the first exception.

The result is that the catch suddenly starts failing to catch the exception. The problem is that if you know about the TPL, you know about AggregateException and expect it, but if you only understand async, you know tasks are involved as you need to use them in the return types of the methods, but probably don’t expect your exceptions to get wrapped. There’s a good write up of the rational behind the decision here.

While we are on the subject, Stephen Toub did another brilliant presentation on Async at //build which can be viewed here.

Advertisements
This entry was posted in Computers and Internet. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s