TaskHelperExtensions.Then can hang indefinitely if the continuation throws an exception

Topics: ASP.NET Web API, General
May 21, 2013 at 10:57 PM
Hi guys,

It's my first time here so apologies if I'm using the wrong channel to raise this issue.

I was unit testing some task based server side logic and found that my tests would just run forever until I hit the cancel button.

The gist of the server code is:
return SomeThingAsync()
.Then((result) => { /* do stuff with result and return a new result*/ })
.Then((result) => { /* do stuff with result and return a new result*/ });
To help me debug, the first thing I did was to swap the lamdas to named methods just to make things clearer in my mind about how things were executing. But I found that this led to an ambiguous invocation. Not realizing I needed explicitly cast the named method to Func<Task>, I instead did the following:
.Then((result) => MyNamedMethod(result));
And all of a sudden my test completed with a failure due to an exception thrown inside MyNamedMethod. How could this be? All I effectively did was to move the body of the lamda into a named function.

I looked into the source code and found that, providing the antecedent task doesn't complete/fail instantly, all roads lead to the TaskHelpers.ThenImplContinuation function.

And this is where things go wrong - if SynchronizationContext.Current is null at the time this method is called - the continuation is invoked without a surrounding try/catch block.

I propose to submit a really simple patch that surrounds this invocation with an appropriate try/catch block of the form:
try
{
    tcs.TrySetResult(continuation(task));
}
catch (Exception ex)
{
    tcs.TrySetException(ex);
}
What steps should I take to submit the patch? I read the guide - but I don't have windows 8 installed (heck - I don't even have .NET 4.5 in my code base). Can someone help me out?