I am starting using Tasks in C#. I am trying to execute this code.
private static void CreateSubtask() {
Task<Int32[]> parent = Task.Run(() =>
{
var results = new Int32[3];
new Task(() => results[0] = 0,
TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[1] = 1,
TaskCreationOptions.AttachedToParent).Start();
new Task(() => results[2] = 2,
TaskCreationOptions.AttachedToParent).Start();
return results;
});
var finalTask = parent.ContinueWith(
parentTask =>
{
foreach (int i in parentTask.Result)
Console.WriteLine(i);
});
finalTask.Wait();
}
The finalTask
runs only after the parent Task
is finished, and the parent Task
finishes when all three children are finished. You can use this to create quite complex Task
hierarchies that will go through all the steps you specified.
What I got from the execution instead is three lines saying:
0
0
0
I was expecting them to be
0
1
2
Am I right?
Using Task.Run
with the parent task suppresses the effect of AttachedToParent
on the child task:
Task.Run vs Task.Factory.StartNew by Stephen Toub.
Use Task.Factory.StartNew
instead.
The problem is that your parent
task completes when it finishes starting the other three tasks, not when the other three tasks are finished.
Instead you can use Task.WhenAll
to create a task that will be completed when all of the other tasks are themselves completed.
Another change to make your program more idiomatic task code is to have each inner task return their own value, rather than mutating some shared state, simply because dealing with shared state can be harder to reason about in a multithreaded environment.
var parent = Task.WhenAll(Task.Run(() => 0),
Task.Run(() => 1),
Task.Run(() => 2));
var finalTask = parent.ContinueWith(t =>
{
foreach (int n in t.Result)
Console.WriteLine(n);
});
finalTask.Wait();
You are only starting your three sub tasks, but not waiting for them to finish. Adapt it like this, for example:
var task1 = new Task(() => results[0] = 0,
TaskCreationOptions.AttachedToParent);
var task2 = new Task(() => results[1] = 1,
TaskCreationOptions.AttachedToParent);
var task3 = new Task(() => results[2] = 2,
TaskCreationOptions.AttachedToParent);
task1.Start();
task2.Start();
task3.Start();
task1.Wait();
task2.Wait();
task3.Wait();
Also note that with your current code, it is still possible to show 0 1 2
(not 1 2 3
by the way), as it is not determined when the subtasks are running / finishing. This might also be dependent on your build configuration (debug / release).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With