A surprise TaskCancelledException

time to read 2 min | 348 words

All of a sudden, my code started getting a lot of TaskCancelledException. It took me a while to figure out what was going on. We can imagine that the code looked like this:

var unwrap = Task.Factory.StartNew(() =>
{
    if (DateTime.Now.Month % 2 != 0)
        return null;

    return Task.Factory.StartNew(() => Console.WriteLine("Test"));
}).Unwrap();

unwrap.Wait();

The key here is that when Unwrap is getting a null task, it will throw a TaskCancelledException, which was utterly confusing to me. It make sense, because if the task is null there isn’t anything that the Unwrap method can do about it. Although I do wish it would throw something like ArgumentNullException with a better error message.

The correct way to write this code is to have:

var unwrap = Task.Factory.StartNew(() =>
{
    if (DateTime.Now.Month % 2 != 0)
    {
        var taskCompletionSource = new TaskCompletionSource<object>();
        taskCompletionSource.SetResult(null);
        return taskCompletionSource.Task;
    }

    return Task.Factory.StartNew(() => Console.WriteLine("Test"));
}).Unwrap();

unwrap.Wait();

Although I do wish that there was an easier way to create a completed task.