Child task canceled, Parent completed?

c#, task-parallel-library

Solution

This is expected behavior as stated on MSDN. The parent task has to wait (scroll down to the cancellation section) for the child task. The parent task has to handle all benign faults (like cancellation).

To make your parent task fail, just wait and pass the token:

Task child = null;
var parent = Task.Factory.StartNew(() =>
{
  child = Task.Factory.StartNew(() =>
  {
    while (!token.IsCancellationRequested) Thread.Sleep(100);
    token.ThrowIfCancellationRequested();
  }, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default);

  // This is the magic line.
  child.Wait(token);
}, token);

If you are using this code to do something productive and not only for testing, you should also consider using the simplified `Task.Run()` which supports `async` delegates instead of `Task.Factory.StartNew()`. This article is very interesting.

Problem

I'm trying to understand the behavior of the .net Tasks, when children is attached. I have the following test code: ``` void Test() { var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; Task child = null; var parent = Task.Factory.StartNew(() => { child = Task.Factory.StartNew(() => { while (!token.IsCancellationRequested) Thread.Sleep(100); token.ThrowIfCancellationRequested(); }, token, TaskCreationOptions.AttachedToParent, TaskScheduler.Default); }, token); Thread.Sleep(500); Debug.WriteLine("State of parent before cancel is {0}", parent.Status); Debug.WriteLine("State of child before cancel is {0}", child.Status); tokenSource.Cancel(); Thread.Sleep(500); Debug.WriteLine("State of parent is {0}", parent.Status); Debug.WriteLine("State of child is {0}", child.Status); } ``` Result of this is: ``` State of parent before cancel is WaitingForChildrenToComplete State of child before cancel is Running A first chance exception of type 'System.OperationCanceledException' occurred in mscorlib.dll State of parent is RanToCompletion State of child is Canceled ``` Aparrently the parent task state is not `Canceled`, even though both tasks share the token, and child is attached. How do i make the parent task return state `Canceled` when a cancellation occurs? NOTE If i throw an exception both tasks return `Faulted`.

Original source