如何让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上的第三级任务中,但它会运行两次。任何帮助,将不胜感激。这是我的示例程序的输出。
答案 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);
它会做我想要的。这是新的输出。