Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What I found works for me, but still doesn't feel as clean as it should:</p> <ul> <li>Each task in the main chain doesn't take the <code>CancellationToken</code>, but gets a second continuation (not part of the main chain) that runs <code>OnlyOnFaulted</code>.</li> <li>Each of those tasks does its work in a child task, then waits on the child task with by calling <code>.Wait(CancellationToken)</code>. When the token is canceled, the Wait call throws an exception, which faults the task that was running. This allows reporting of the error without waiting on the child task to complete.</li> <li>Every task in the main chain runs <code>OnlyOnRanToCompletion</code>.</li> <li>One task at the end of the main chain that runs <code>OnlyOnRanToCompletion</code> reports success of the entire chain (i.e. no timeout).</li> </ul> <p>When the token is canceled, the currently-running task stops waiting for its child task with an <code>OperationCanceledException</code>. The side branch for that task handles the exception (or any other exception) by special-casing the presence of <code>OperationCanceledException</code> in the antecedent's <code>AggregateException.InnerExceptions</code>. Since the task in the main chain faulted, no other task in the main chain will run.</p> <pre><code>CancellationTokenSource cts = new CancellationTokenSource(25000); Task workChain = Task.Factory.StartNew((o) =&gt; { Console.WriteLine("Running task {0} with state {1}", Task.CurrentId, o); Thread.Sleep(1000); }, -1); Task parent = workChain; for (int i = 0; i &lt; 10; i++) { parent = parent.ContinueWith((ante, o) =&gt; { Console.WriteLine("Running task {0} with state {1}", Task.CurrentId, o); Task subTask = Task.Factory.StartNew(() =&gt; { Thread.Sleep(10000); Console.WriteLine("Subtask completed"); }); subTask.Wait(cts.Token); }, i, TaskContinuationOptions.OnlyOnRanToCompletion); parent.ContinueWith((ante) =&gt; { foreach (Exception e in ante.Exception.InnerExceptions) { if (e is OperationCanceledException) { //report timeout Console.WriteLine("Timed out while running task id {0}", ante.Id); return; } } //report other exception Console.WriteLine("Something bad happened: {0}", ante.Exception.GetBaseException()); }, TaskContinuationOptions.OnlyOnFaulted); } Task lastTask = parent.ContinueWith((ante) =&gt; { //report success Console.WriteLine("Success"); }, TaskContinuationOptions.OnlyOnRanToCompletion); </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload