Reputation: 3963
How do I get a ContinueWith
to wait for two tasks to complete instead of just one?
I wanted to determine how I can chain a set of Task
s together and have one run after the other having several levels of chaining. I have three levels of chaining. In the fist level I have a single task. I wanted the top level to finish before the second level starts. In the second level I have 3 tasks. I want 2 of the three tasks to complete before the third level starts.
TopLevel > SecondLevel A \ ThirdLevel
SecondLevel B /
SecondLevel C - Don't wait for this one for the third level
I have written the following sample program to test out how this would work as follows
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);
}
}
For the most part this does exactly what I want. It starts the first task and waits for it to finish, starts the 3 second level tasks in parallel. However, I can't figure out how to set up the third level to wait for both taskA and taskB since the ContinueWith
is set with a single parent task.
I have attempted to put ContinueWith
for the third level task on both taskA and taskB but then it runs twice. Any help would be appreciated. Here is the output of my sample program.
Upvotes: 0
Views: 2588
Reputation: 244958
You're looking for ContinueWhenAll()
:
Task thirdLevelTask = Task.Factory.ContinueWhenAll(
new[] { secondLevelTaskA, secondLevelTaskB },
tasks => DoSomeWork("thirdLevelTask"),
TaskContinuationOptions.AttachedToParent);
The advantage of this over Task.WhenAll().ContinueWith()
is that it will work on .Net 4.0 too. And if you're on .Net 4.5, it would be probably better to use async
-await
instead of ContinueWith()
.
Upvotes: 4
Reputation: 3963
I figured it out. If I replace
Task thirdLevelTask = secondLevelTaskA.ContinueWith((task) => DoSomeWork("thirdLevelTask"), TaskContinuationOptions.AttachedToParent);
with
Task thirdLevelTask = Task.WhenAll(secondLevelTaskA,secondLevelTaskB).ContinueWith((task) => DoSomeWork("thirdLevelTask"), TaskContinuationOptions.AttachedToParent);
It will do what I want. Here is the new output.
Upvotes: 0