CSharp Task Asynchronous Programming

Last Updated: 2/14/2022

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 the TaskFactory.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");
}

Example

References

https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/attached-and-detached-child-tasks