TPL:Task.Factory.ContinueWhenAll with AttachedToParent

时间:2017-01-24 23:19:20

标签: c# task-parallel-library continuations

description of AttachedToParent

  

AttachedToParent:指定延续(如果是子任务)附加到任务层次结构中的父级。 只有在其前提也是子任务的情况下,延续才能成为子任务。

强调部分是什么意思?以下代码是否与此声明相矛盾?

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();
}

当我运行它时,它会给出这个输出:

Antecedent begun
Parent begun
Parent status: WaitingForChildrenToComplete

延续任务似乎已附加到父级。根据文档,要附加,它必须是一个儿童任务。但是先行者不是一个孩子的任务。

2 个答案:

答案 0 :(得分:0)

嗯,你想要在孩子身上定义那个属性,而不是父亲......这应该是这样的:

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();

答案 1 :(得分:0)

您正在parent任务中创建一个新的子任务 ,直接声明这是一项子任务。这就是parent等待它的原因。如果你在code of the ContinueWhenAll内看到,你会看到这一行:

var starter = TaskFactory.CommonCWAllLogic(tasksCopy);

因此,复制任务,之后在内部创建新任务,这就是继续被标记为子的原因。如果你移出parent的延续,它就不会等待:

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();
}

给定代码的输出为:

Antecedent begun
Parent begun