What is the difference between Task.Run() and Task.Factory.StartNew() What is the difference between Task.Run() and Task.Factory.StartNew() multithreading multithreading

What is the difference between Task.Run() and Task.Factory.StartNew()


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 thenew Task.Run method. This in no way obsoletes Task.Factory.StartNew,but rather should simply be thought of as a quick way to useTask.Factory.StartNew without needing to specify a bunch ofparameters. It’s a shortcut. In fact, Task.Run is actuallyimplemented in terms of the same logic used for Task.Factory.StartNew,just passing in some default parameters. When you pass an Action toTask.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:

  1. 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

  2. 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 here

So 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);