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"?
A continuation task (also known just as a continuation) is an asynchronous task that's invoked by another task, known as the antecedent, when the antecedent finishes.
ContinueWith(Action<Task>)Creates a continuation that executes asynchronously when the target Task completes.
c# - Run sequence of tasks, one after the other - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.
I think your main problem is that you're telling those two tasks to "Wait" with your call to
Task.WaitAll(onSuccess, onError);
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(...)
with taskThrows.Start();
I believe you will get the desired output.
Here is a bit of an example I put together:
class Program { static int DivideBy(int divisor) { Thread.Sleep(2000); return 10 / divisor; } static void Main(string[] args) { const int value = 0; var exceptionTask = new Task<int>(() => DivideBy(value)); exceptionTask.ContinueWith(result => Console.WriteLine("Faulted ..."), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.AttachedToParent); exceptionTask.ContinueWith(result => Console.WriteLine("Success ..."), TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.AttachedToParent); exceptionTask.Start(); try { exceptionTask.Wait(); } catch (AggregateException ex) { Console.WriteLine("Exception: {0}", ex.InnerException.Message); } Console.WriteLine("Press <Enter> to continue ..."); Console.ReadLine(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With