Task.ContinueWith链序列的事件

时间:2013-10-12 17:13:34

标签: c# multithreading asynchronous task-parallel-library task

如何让ContinueWith等待两个任务完成而不只是一个?

我想确定如何将一组Task链接在一起并在另一组具有多个链接级别之后运行。我有三个级别的链接。在第一级我只有一个任务。我希望在第二级开始之前完成顶级。在第二级,我有3个任务。我希望在第三级开始之前完成三个任务中的两个。


TopLevel > SecondLevel A \ ThirdLevel 
           SecondLevel B /
           SecondLevel C - Don't wait for this one for the third level

我编写了以下示例程序来测试它如何工作如下

class Program
{
    private static Random rand = new Random();
    public static Random Rand { get { return rand; } }
    static void Main(string[] args)
    {

        Task topLevelTask = new Task(() => DoSomeWork("topLevelTask"));
        Task secondLevelTaskA = topLevelTask.ContinueWith((task) => DoSomeWork("secondLevelTaskA"), TaskContinuationOptions.AttachedToParent);
        Task secondLevelTaskB = topLevelTask.ContinueWith((task) => DoSomeWork("secondLevelTaskB"), TaskContinuationOptions.AttachedToParent);
        Task secondLevelTaskC = topLevelTask.ContinueWith((task) => DoSomeWork("secondLevelTaskC"), TaskContinuationOptions.AttachedToParent);
        Task thirdLevelTask = secondLevelTaskA.ContinueWith((task) => DoSomeWork("thirdLevelTask"), TaskContinuationOptions.AttachedToParent);

        topLevelTask.Start();
        Console.ReadLine();
    }

    private static void DoSomeWork(string task)
    {
        int sleep = Rand.Next(10000);
        Console.WriteLine("Thread {0}: Ticks {1}: Task {2}: Sleep: {3}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task, sleep);
        Thread.Sleep(sleep);
        Console.WriteLine("Complete Task {0}", task);
    }
}

在大多数情况下,这正是我想要的。它启动第一个任务并等待它完成,并行启动3个二级任务。但是,我无法弄清楚如何设置第三级以等待taskA和taskB,因为ContinueWith设置了单个父任务。

我试图将ContinueWith放在taskA和taskB上的第三级任务中,但它会运行两次。任何帮助,将不胜感激。这是我的示例程序的输出。

Program Output

2 个答案:

答案 0 :(得分:4)

您正在寻找ContinueWhenAll()

Task thirdLevelTask = Task.Factory.ContinueWhenAll(
    new[] { secondLevelTaskA, secondLevelTaskB },
    tasks => DoSomeWork("thirdLevelTask"),
    TaskContinuationOptions.AttachedToParent);

这优于Task.WhenAll().ContinueWith()的优势在于它也适用于.Net 4.0。如果您使用.Net 4.5,最好使用async - await代替ContinueWith()

答案 1 :(得分:0)

我明白了。如果我更换

Task thirdLevelTask = secondLevelTaskA.ContinueWith((task) => DoSomeWork("thirdLevelTask"), TaskContinuationOptions.AttachedToParent);

Task thirdLevelTask = Task.WhenAll(secondLevelTaskA,secondLevelTaskB).ContinueWith((task) => DoSomeWork("thirdLevelTask"), TaskContinuationOptions.AttachedToParent);

它会做我想要的。这是新的输出。

enter image description here