Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Tasks with conditional continuations

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"?

like image 898
dan Avatar asked Apr 11 '11 19:04

dan


People also ask

What is Task continuation?

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.

What does calling task ContinueWith () do?

ContinueWith(Action<Task>)Creates a continuation that executes asynchronously when the target Task completes.

Which code creates a chain of task to be executed after one another?

c# - Run sequence of tasks, one after the other - Stack Overflow. Stack Overflow for Teams – Start collaborating and sharing organizational knowledge.


1 Answers

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();     } } 
like image 196
Bryan Ray Avatar answered Sep 19 '22 12:09

Bryan Ray