0

The description of AttachedToParent states

AttachedToParent: Specifies that the continuation, if it is a child task, is attached to a parent in the task hierarchy. The continuation can be a child task only if its antecedent is also a child task.

What does the emphasized part mean? Does the following code contradict this statement?

static void Example()
{
    Task antecedent = new Task(() =>
        {
            Console.WriteLine("Antecedent begun");
            Thread.Sleep(1000);
        });
    antecedent.Start();

    Task parent = null;
    parent = new Task(() =>
        {
            Console.WriteLine("Parent begun");
            Thread.Sleep(500);
            var continuation = Task.Factory.ContinueWhenAll(new[] { antecedent }, _ =>
            {
                    Thread.Sleep(2000);
                    Console.WriteLine("parent status: {0}", parent.Status);

            }, TaskContinuationOptions.AttachedToParent);
        });
    parent.Start();
    parent.Wait();
}

When I run this, it gives this output:

Antecedent begun
Parent begun
Parent status: WaitingForChildrenToComplete

The continuation task does appear to have been attached to the parent. According to the documentation, to be attached, it must be a child task. But antecedent isn't a child task.

VMAtm
  • 27,943
  • 17
  • 79
  • 125
Rob
  • 4,327
  • 6
  • 29
  • 55
  • Continuation task is **not** the same as antecedent, it's a different tasks. What's your question? – VMAtm Feb 09 '17 at 04:13
  • @WMAtm. I'm looking to resolve an apparent ambiguity/contradiction in the documentation. Is `continuation` a child task of `parent`? It appears to be, as the parent waits for children to complete. But the doc states that it cannot be, because the `continuation`'s antecedent is not a child task of `parent`. – Rob Feb 10 '17 at 09:50
  • `Continuation` is a child of `parent` task, yes. `Parent` is not aware about what's going on inside the `continuation`, it simply waits for it. You're creating a new task with `WhenAll`, you're not continuing the `antecedent` directly. – VMAtm Feb 10 '17 at 13:43

2 Answers2

0

Well, you want that property to be defined on the child, not the parent ... It should look something like :

Task parent = null;

var antecedent = new Task(() =>
{
    Console.WriteLine("Antecedent begun");
    Thread.Sleep(1000);
}, new CancellationToken(), TaskCreationOptions.AttachedToParent);
antecedent.Start();

parent = new Task(() =>
    {
        Console.WriteLine("Parent begun");
        Thread.Sleep(500);
        Task.Factory.ContinueWhenAll(new[] { antecedent }, _ =>
        {
            Thread.Sleep(2000);
            Console.WriteLine("parent status: {0}", parent.Status);

        });
    });
parent.Start();
parent.Wait();
Noctis
  • 11,507
  • 3
  • 43
  • 82
  • It's the continuation task (created by `ContinueWhenAll`) that I am attaching to the parent task `parent`, but the antecedent of the continuation task is not a child of `parent`. But the bold text seems to say that this is not possible. – Rob Jan 25 '17 at 10:04
0

You're creating a new child task inside the parent task with directly stating that this is a child task. This is why the the parent waits for it. If you see inside the code of the ContinueWhenAll, you'll see this line:

var starter = TaskFactory.CommonCWAllLogic(tasksCopy);

So, the tasks are copied, and after that the new task is internally created, this is why the continuation is marked as child. If you move out the continuation out of parent, it wouldn't be wait for:

static void Example2()
{
    Task antecedent = new Task(() =>
    {
        Console.WriteLine("Antecedent begun");
        Thread.Sleep(1000);
    });
    antecedent.Start();

    Task parent = new Task(() =>
    {
        Console.WriteLine("Parent begun");
        Thread.Sleep(500);
    });
    Task.Factory.ContinueWhenAll(new[] { antecedent }, _ =>
    {
        Thread.Sleep(2000);
        Console.WriteLine("parent status: {0}", parent.Status);

    }, TaskContinuationOptions.AttachedToParent);
    parent.Start();
    parent.Wait();
}

Output for the given code is:

Antecedent begun
Parent begun
VMAtm
  • 27,943
  • 17
  • 79
  • 125