So here is my code
Task<int[]> parent = Task.Run(() =>
{
var result = new int[3];
TaskFactory tf = new TaskFactory(TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously);
for (int i = 0; i < result.Length; i++)
{
int j = i;
tf.StartNew(() => result[j] = GetRandomNumber(j));
}
return result;
});
var finalTask = parent.ContinueWith(parentTask =>
{
foreach (var i in parentTask.Result)
{
Console.WriteLine(i);
}
});
finalTask.Wait();
Basically I create 3 Task
s which are children of Task
called parent (I guess). I excpect parent task to wait for all three child tasks to complete. After that the finalTask
would be waited to execute because of finalTask.Wait();
this statemant. But things do not happen as expected. I mean the application exits before the any of GetRandomNumber
calls finishes. Some part of the code in here is copied from book which stated that those parent task should wait for child task to complete which apparently is not happening. Am I missing something here ?
this is what GetRandomNumber does
public static int GetRandomNumber(int ii)
{
Random rand = new Random();
for (int i = 0; i < 1000000000; i++) { } // imitate some jobs
return rand.Next(1000);
}
This code does the same thing
Task<int[]> parent = Task.Run(() =>
{
var result = new int[3];
for (int i = 0; i < result.Length; i++)
{
int j = i;
new Task(() => result[j] = GetRandomNumber(j), TaskCreationOptions.AttachedToParent).Start();
}
return result;
});
A child task can be either detached or attached. A detached child task is a task that executes independently of its parent. An attached child task is a nested task that is created with the TaskCreationOptions. AttachedToParent option whose parent does not explicitly or by default prohibit it from being attached.
Parent Task is a high-level item within task breakdown that is specified with greater detail by a number of related sub-tasks or child tasks. It is the root task that subordinates its sub-tasks and defines how they should be performed and related to each other.
Wait is a synchronization method that causes the calling thread to wait until the current task has completed. If the current task has not started execution, the Wait method attempts to remove the task from the scheduler and execute it inline on the current thread.
This behaviour is due to your use of the Task.Run
method, which forbids child tasks from being attached to the parent:
The
Run
method is a simpler alternative to theStartNew
method. It creates a task [whose]CreationOptions
property value isTaskCreationOptions.DenyChildAttach
.
To resolve, simply change your first line from
Task<int[]> parent = Task.Run(() =>
to
Task<int[]> parent = Task.Factory.StartNew(() =>
In Task.Run's documentation, you'll find that it specifies
Its CreationOptions property value is TaskCreationOptions.DenyChildAttach.
So, even though you specify TaskCreationOptions.AttachedToParent
, it is ignored.
Please use the code as below:
static void RunParentTask()
{
Task<int[]> parent = Task.Factory.StartNew<int[]>(() =>
{
var results = new int[3];
TaskFactory<int> factory = new TaskFactory<int>(TaskCreationOptions.AttachedToParent,
TaskContinuationOptions.ExecuteSynchronously);
factory.StartNew(() => results[0] = 1);
factory.StartNew(() => results[1] = 2);
factory.StartNew(() => results[2] = 3);
return results;
});
parent.Wait();
foreach (var item in parent.Result)
{
Console.WriteLine(item);
}
}
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