Reputation: 2878
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;
});
Upvotes: 7
Views: 4583
Reputation: 129
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);
}
}
Upvotes: 2
Reputation: 54917
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(() =>
Upvotes: 14
Reputation: 17474
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.
Upvotes: 8