I'm a little confused about how to use Tasks with conditional Continuations.
If I have a task, and then I want to continue with a tasks that handle success and error, and then wait on those to complete.
void FunctionThrows() {throw new Exception("faulted");}
static void MyTest()
{
var taskThrows = Task.Factory.StartNew(() => FunctionThrows());
var onSuccess = taskThrows.ContinueWith(
prev => Console.WriteLine("success"),
TaskContinuationOptions.OnlyOnRanToCompleted);
var onError = taskThrows.ContinueWith(
prev => Console.WriteLine(prev.Exception),
TaskContinuationOptions.OnlyOnFaulted);
//so far, so good
//this throws because onSuccess was cancelled before it was started
Task.WaitAll(onSuccess, onError);
}
Is this the preferred way of doing task success/failure branching? Also, how am I supposed to join all these tasks, suppose I've created a long line of continuations, each having their own error handling.
//for example
var task1 = Task.Factory.StartNew(() => ...)
var task1Error = task1.ContinueWith( //on faulted
var task2 = task1.ContinueWith( //on success
var task2Error = task2.ContinueWith( //on faulted
var task3 = task2.ContinueWith( //on success
//etc
Calling WaitAll
on these invariably throws, because some of the continuations will be cancelled due to the TaskContinuationOptions
, and calling Wait
on a cancelled task throws.
How do I join these without getting the "A task was cancelled" exception"?
Isn't that normal?
Looking at the MSDN documentation you're doing it fine and the logic you're implementing is sound. The only thing you're missing is wrapping the WaitAll call in an AggregateException wrapper like so:
You can read more here: http://msdn.microsoft.com/en-us/library/dd270695.aspx
In essence catching an AggregatedException gets you the same thing as completing WaitAll. It's a collection of all the exceptions returned from your tasks.
Use
Task.WaitAny(onSuccess, onError);
I think your main problem is that you're telling those two tasks to "Wait" with your call to
The onSuccess and onError continuations are automatically setup for you and will be executed after their antecedent task completes.
If you simply replace your
Task.WaitAll(...)
withtaskThrows.Start();
I believe you will get the desired output.Here is a bit of an example I put together: