Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task composition and error handling with TPL

I have a method with the following structure:

public Task InitializeAsync()
{
    var taskCompletionSource = new TaskCompletionSource<bool>();

    Task firstTask = ...;

    // secondTask calls taskCompletionSource.TrySetResult(true) once it considers itself "done"
    Task secondTask = firstTask.ContinueWith(..., TaskContinuationOptions.OnlyOnRanToCompletion);

    Action<TasK> errorContinuation = x =>
        {
            taskCompletionSource.SetException(e.Exception);
        };

    firstTask.ContinueWith(errorContinuation, TaskContinuationOptions.OnlyOnFaulted);
    secondTask.ContinueWith(errorContinuation, TaskContinuationOptions.OnlyOnFaulted);

    return taskCompletionSource.Task;
}

Importantly:

  • the task returned by InitializeAsync isn't considered complete until the secondTask decides so
  • secondTask only runs if firstTask is successful
  • failure of either firstTask or secondTask causes the overall task to fail

What I'm wondering is whether there's a cleaner, simpler way to express this whilst achieving the same functionality. I'm using .NET 4.0 but am interested in whether 4.5 makes this easier, too.

like image 854
Kent Boogaart Avatar asked Mar 06 '12 16:03

Kent Boogaart


1 Answers

For .NET 4.0, I used an idea from this blog article to chain tasks like you describe. In particular, look at the section titled Then. Not that his version expects you to pass in a function that returns a task instead of just passing a method like you would to ContinueWith

As an aside, Then gets you pretty close to the SelectMany you would need to be able to chain the tasks via LINQ from clauses. I mention this mostly as a syntax option until async/await in .NET 4.5, though I don't actually use that myself.

like image 65
Gideon Engelberth Avatar answered Oct 10 '22 11:10

Gideon Engelberth