Why the default value for CreationOptions
of a Task
created using Task.Run
is DenyChildAttach
rather than None
?
Has it anything to do with making work with the new async
and await
in C# 5.0 simpler (by preventing you from escaping current scheduler of current context I guess)?
NET code does not mean there are separate new threads involved. Generally when using Task. Run() or similar constructs, a task runs on a separate thread (mostly a managed thread-pool one), managed by the . NET CLR.
Task. Run(action) internally uses the default TaskScheduler , which means it always offloads a task to the thread pool. StartNew(action) , on the other hand, uses the scheduler of the current thread which may not use thread pool at all!
StartNew(Action, CancellationToken) Creates and starts a task for the specified action delegate and cancellation token. StartNew(Action, TaskCreationOptions) Creates and starts a task for the specified action delegate and creation options.
The Run method allows you to create and execute a task in a single method call and is a simpler alternative to the StartNew method. It creates a task with the following default values: Its cancellation token is CancellationToken.
Why the default value for CreationOptions of a Task created using Task.Run is DenyChildAttach rather than None?
There is no (default or other) options in creating a task using Task.Run Method.
Citing from Task.Run vs Task.Factory.StartNew (by Stephen Toub - MSFT):
Task.Run(someAction);
is exactly equivalent to:
Task.Factory.StartNew
( someAction
, CancellationToken.None
, TaskCreationOptions.DenyChildAttach
, TaskScheduler.Default
);
MSDN article Nested Tasks and Child Tasks (for .NET 4.0, i.e. without any equivokes for C# 5.0/.NET 4.5) states:
"in most scenarios, we recommend that you use nested tasks because the relationships with other tasks are less complex. That is why tasks created inside other tasks are nested by default, and you must explicitly specify the AttachedToParent option to create a child task"
which explains why CreationOptions.DenyChildAttach
was chosen for the shortcut's most common and simplest option.
Stephen Toub explains this well in his blog post on the subject.
Parent and child tasks are somewhat common when using Task
s in a parallel fashion. Note that when a parent Task
has a child, the parent's completion semantics change subtly.
Parent/child tasks are almost never used when using Task
s in an async
fashion. In the async
world, you have a sort of "logical parent/child relationship" when one async
method calls another, but it is not actually implemented using parent/child tasks.
Usually a Task
intended for use in async
code is not expecting to have its completion semantics changed by a child task attaching to it. Thus, the new default for Task.Run
is DenyChildAttach
, which prevents any child tasks attempting to attach.
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