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
InitializeAsyncisn’t considered complete until the secondTask decides so secondTaskonly runs iffirstTaskis successful- failure of either
firstTaskorsecondTaskcauses 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.
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
ContinueWithAs an aside,
Thengets you pretty close to theSelectManyyou 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.