I have Method :
private static void Method()
{
Console.WriteLine("Method() started");
for (var i = 0; i < 20; i++)
{
Console.WriteLine("Method() Counter = " + i);
Thread.Sleep(500);
}
Console.WriteLine("Method() finished");
}
And I want to start this method in a new Task. I can start new task like this
var task = Task.Factory.StartNew(new Action(Method));
or this
var task = Task.Run(new Action(Method));
But is there any difference between Task.Run()
and Task.Factory.StartNew()
. Both of them are using ThreadPool and start Method() immediately after creating instance of the Task. When we should use first variant and when second?
StartNew(Action<Object>, Object, CancellationToken, TaskCreationOptions, TaskScheduler) Creates and starts a task for the specified action delegate, state, cancellation token, creation options and task scheduler.
The TaskFactory class, which creates Task and Task<TResult> objects. You can call the overloads of this method to create and execute a task that requires non-default arguments.
Task Factory streamlines many tedious data warehousing management tasks, including upserting data. Learn more about how to upsert data faster Learn more about how to upsert data faster. Close.
Differences Between Task And ThreadThe Thread class is used for creating and manipulating a thread in Windows. A Task represents some asynchronous operation and is part of the Task Parallel Library, a set of APIs for running tasks asynchronously and in parallel. The task can return a result.
The second method, Task.Run
, has been introduced in a later version of the .NET framework (in .NET 4.5).
However, the first method, Task.Factory.StartNew
, gives you the opportunity to define a lot of useful things about the thread you want to create, while Task.Run
doesn't provide this.
For instance, lets say that you want to create a long running task thread. If a thread of the thread pool is going to be used for this task, then this could be considered an abuse of the thread pool.
One thing you could do in order to avoid this would be to run the task in a separate thread. A newly created thread that would be dedicated to this task and would be destroyed once your task would have been completed. You cannot achieve this with the Task.Run
, while you can do so with the Task.Factory.StartNew
, like below:
Task.Factory.StartNew(..., TaskCreationOptions.LongRunning);
As it is stated here:
So, in the .NET Framework 4.5 Developer Preview, we’ve introduced the new Task.Run method. This in no way obsoletes Task.Factory.StartNew, but rather should simply be thought of as a quick way to use Task.Factory.StartNew without needing to specify a bunch of parameters. It’s a shortcut. In fact, Task.Run is actually implemented in terms of the same logic used for Task.Factory.StartNew, just passing in some default parameters. When you pass an Action to Task.Run:
Task.Run(someAction);
that’s exactly equivalent to:
Task.Factory.StartNew(someAction,
CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
People already mentioned that
Task.Run(A);
Is equivalent to
Task.Factory.StartNew(A, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
But no one mentioned that
Task.Factory.StartNew(A);
Is equivalent to:
Task.Factory.StartNew(A, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Current);
As you can see two parameters are different for Task.Run
and Task.Factory.StartNew
:
TaskCreationOptions
- Task.Run
uses TaskCreationOptions.DenyChildAttach
which means that children tasks can not be attached to the parent, consider this:
var parentTask = Task.Run(() =>
{
var childTask = new Task(() =>
{
Thread.Sleep(10000);
Console.WriteLine("Child task finished.");
}, TaskCreationOptions.AttachedToParent);
childTask.Start();
Console.WriteLine("Parent task finished.");
});
parentTask.Wait();
Console.WriteLine("Main thread finished.");
When we invoke parentTask.Wait()
, childTask
will not be awaited, even though we specified TaskCreationOptions.AttachedToParent
for it, this is because TaskCreationOptions.DenyChildAttach
forbids children to attach to it. If you run the same code with Task.Factory.StartNew
instead of Task.Run
, parentTask.Wait()
will wait for childTask
because Task.Factory.StartNew
uses TaskCreationOptions.None
TaskScheduler
- Task.Run
uses TaskScheduler.Default
which means that the default task scheduler (the one that runs tasks on Thread Pool) will always be used to run tasks. Task.Factory.StartNew
on the other hand uses TaskScheduler.Current
which means scheduler of the current thread, it might be TaskScheduler.Default
but not always. In fact when developing Winforms
or WPF
applications it is required to update UI from the current thread, to do this people use TaskScheduler.FromCurrentSynchronizationContext()
task scheduler, if you unintentionally create another long running task inside task that used TaskScheduler.FromCurrentSynchronizationContext()
scheduler the UI will be frozen. A more detailed explanation of this can be found hereSo generally if you are not using nested children task and always want your tasks to be executed on Thread Pool it is better to use Task.Run
, unless you have some more complex scenarios.
See this blog article that describes the difference. Basically doing:
Task.Run(A)
Is the same as doing:
Task.Factory.StartNew(A, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
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