Attached and Detached Child Tasks
- A parent task can create a nested child task.
- A child task can be either attached or detached.
- A detached child task executes independently of its parent. Default and Recommended.
- An attached child task is created with
TaskCreationOptions.AttachedToParent
.
Detached Child Task
Parent task and child tasks execute independently of each other.
Creating Detached Child Task
var parentTask = Task.Factory.StartNew(() => {
Console.WriteLine("Parent task executing");
var childTask = Task.Factory.StartNew(() => {
Console.WriteLine("Child task executing");
Thread.SpinWait(500000);
Console.WriteLine("Child task completed");
});
});
parentTask.Wait();
Console.WriteLine("Parent task completed");
Waiting For Detached Child Task
The parent task will wait for the child to complete by accessing the Task<TResult>.Result
property of the child even if it is a detached child task. The Result property blocks until its task completes.
var parentTask = Task.Factory.StartNew(() => {
Console.WriteLine("Parent task executing");
var childTask = Task<string>.Factory.StartNew(() => {
Console.WriteLine("Child task executing");
Thread.SpinWait(500000);
Console.WriteLine("Child task completed");
return "success";
});
Console.WriteLine(childTask.Result);
});
parentTask.Wait();
Console.WriteLine("Parent task completed");
Attached Child Task
Creating Attached Child Task
- Use
AttachedToParent
option to create an attached child task of the parent task. - The parent task implicitly waits for all attached child tasks to finish.
- Parent propagates exceptions thrown by child tasks.
- Status of parent depends on status of child.
- Parent tasks can explicitly prevent child tasks from attaching to them by specifying the
TaskCreationOptions.DenyChildAttach
option in the parent task's class constructor or theTaskFactory.StartNew
method. - Parent task created with
Task.Run
implicitly prevent child tasks from attaching to them
var parentTask = Task.Factory.StartNew(() => {
Console.WriteLine("Parent task executing");
for(int i = 0; i < 10; i++)
{
Task.Factory.StartNew((taskNo) => {
Console.WriteLine($"Attached child task {taskNo} completed");
}, i, TaskCreationOptions.AttachedToParent);
}
});
parentTask.Wait();
Console.WriteLine("Parent task completed");
Preventing Child Task from Attaching to its Parent
Preventing a child task from attaching to its parent is useful when you call a component that is written by a third party and uses TaskCreationOptions.AttachedToParent
option to create a Task or Task<TResult>
object, which can cause problems in your code if it is long-running or throws an unhandled exception.
Use TaskCreationOptions.DenyChildAttach
to prevent child task from attaching to its parent
private static void PreventChildFromAttaching()
{
var parentTask = Task.Factory.StartNew(() => {
Console.WriteLine("Parent task executing");
for(int i = 0; i < 10; i++)
{
Task.Factory.StartNew((taskNo) => {
Console.WriteLine($"Attached child task {taskNo} completed");
}, i, TaskCreationOptions.AttachedToParent);
}
}, TaskCreationOptions.DenyChildAttach);
parentTask.Wait();
Console.WriteLine("Parent task completed");
}