Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Questions regarding Task Programming

What are the main differences between the following conventions.

First:

Task myTask = new Task(()=>
{
     // executable statements
});
myTask.Start();

Second:

Task.Run(()=>
{
  // executable statements
});

Third:

  Task.Factory.StartNew(() =>
  {
       // executable statements
  });
like image 910
Stephan Ronald Avatar asked Jul 17 '26 16:07

Stephan Ronald


1 Answers

Firstly, this information is avalible with a simple google.

A. From MSDN "Task.Factory.StartNew" vs "new Task(...).Start"

With TPL, there are several ways to create and start a new task. One way is to use the constructor for task followed by a call to the Start method, e.g.

new Task(...).Start();

and the other is by using the StartNew method of TaskFactory, e.g.

Task.Factory.StartNew(...);

This begs the question... when and why would you use one approach versus the other?

In general, I always recommend using Task.Factory.StartNew unless the particular situation provides a compelling reason to use the constructor followed by Start. There are a few reasons I recommend this. For one, it's generally more efficient. For example, we take a lot of care within TPL to make sure that when accessing tasks from multiple threads concurrently, the "right" thing happens. A Task is only ever executed once, and that means we need to ensure that multiple calls to a task's Start method from multiple threads concurrently will only result in the task being scheduled once. This requires synchronization, and synchronization has a cost. If you construct a task using the task's constructor, you then pay this synchronization cost when calling the Start method, because we need to protect against the chance that another thread is concurrently calling Start. However, if you use Task.Factory.StartNew, we know that the task will have already been scheduled by the time we hand the task reference back to your code, which means it's no longer possible for threads to race to call Start, because every call to Start will fail. As such, for StartNew we can avoid that additional synchronization cost and take a faster path for scheduling the task.

B. From MSDN Task.Run vs Task.Factory.StartNew

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

In this way, Task.Run can and should be used for the most common cases of simply offloading some work to be processed on the ThreadPool (what TaskScheduler.Default targets). That doesn’t mean Task.Factory.StartNew will never again be used; far from it. Task.Factory.StartNew still has many important (albeit more advanced) uses. You get to control TaskCreationOptions for how the task behaves. You get to control the scheduler for where the task should be queued to and run. You get to use overloads that accept object state, which for performance-sensitive code paths can be used to avoid closures and the corresponding allocations. For the simple cases, though, Task.Run is your friend.

I hope this helps.

like image 103
MoonKnight Avatar answered Jul 20 '26 04:07

MoonKnight



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!