Differencebetween Task.Run() and Task.Factory.Startnew()

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

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

Read more here.

If you pass CancellationToken.None, TaskCreationOptions.DenyChildAttach and TaskScheduler.Default arguments for Task.Factory.StartNew parameters you should see the same result.

different behavior between Factory.StartNew and Task.Run?

The return type from the task factory is Task <Task>, the return type of Task.Run is just Task.

You need to unwrap the inner task with the factory so that your ConinueWith in the queue code is running the continuation on the inner task instead of the outer task.

static void Main(string[] args)
{
Console.WriteLine($"Starting test program (ManagedThreadId={Thread.CurrentThread.ManagedThreadId} IsThreadPoolThread={Thread.CurrentThread.IsThreadPoolThread})");

SerialTaskQueue co_pQueue = new SerialTaskQueue();

for (int i = 0; i < 2; i++)
{
var local = i;
co_pQueue.Enqueue(() => Task.Factory.StartNew(() => { return SimulateTaskSequence(local); }, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default).Unwrap());
}
}

Task.Run has a overload that accepts a Func<Task> that does this for you. If you declared the delegate in the Task.Run as a Func<object> you would see the same behavior from the Task.Run.

What is difference between Task.Factory.StartNew and new Thread().Start()?

  • Task.Factory.StartNew : Starts a new task that will run in a thread pool thread or may run in the same thread. If it is ran in a thread pool thread, the thread is returned to the pool when done. Thread creation/destruction is an expensive process.

  • new Thread().Start() : Will always run in a new thread, therefore, it is more expensive.

The exception means that there is an ongoing data set being readed from somewhere else, and you are trying to open another data reader at the same time. When using tasks, maybe you are executing one task after the other, and that is why you don't get the exception.

The exception is not threading related. You can get the same exception by opening a data reader, and try to open a new one without closing the first.

I would suggest to review your code considering that, and ensure you need threading before use it. Multithreading overuse creates performance problems and incredibly ugly bugs.

Regarding usage of Task.Start() , Task.Run() and Task.Factory.StartNew()

Task.Run is a shorthand for Task.Factory.StartNew with specific safe arguments:

Task.Factory.StartNew(
action,
CancellationToken.None,
TaskCreationOptions.DenyChildAttach,
TaskScheduler.Default);

It was added in .Net 4.5 to help with the increasingly frequent usage of async and offloading work to the ThreadPool.

Task.Factory.StartNew (added with TPL in .Net 4.0) is much more robust. You should only use it if Task.Run isn't enough, for example when you want to use TaskCreationOptions.LongRunning (though it's unnecessary when the delegate is async. More on that on my blog: LongRunning Is Useless For Task.Run With async-await). More on Task.Factory.StartNew in Task.Run vs Task.Factory.StartNew

Don't ever create a Task and call Start() unless you find an extremely good reason to do so. It should only be used if you have some part that needs to create tasks but not schedule them and another part that schedules without creating. That's almost never an appropriate solution and could be dangerous. More in "Task.Factory.StartNew" vs "new Task(...).Start"

In conclusion, mostly use Task.Run, use Task.Factory.StartNew if you must and never use Start.

Task.Factory.StartNew() vs. TaskEx.Run()

Anders Hejlsberg talked about that briefly in an interview on Channel9. Apparently, Task.Run is just a shorthand for Task.Factory.StartNew. Its still early CTP days so we're unsure that Task.Run will make it int. I personally hope it won't because it's kind of redundant. :)

Task.Factory.StartNew vs new Task

I found this great article by Stephen Toub, which explains that there is actually a performance penalty when using new Task(...).Start(), as the start method needs to use synchronization to make sure the task is only scheduled once.

His advice is to prefer using Task.Factory.StartNew for .net 4.0. For .net 4.5 Task.Run is the better option.

Task.Run vs Task.Factory.StartNew - Expected Deadlock is not happening

The method Task.Factory.StartNew when used with an async delegate returns a nested task: Task<Task>. You are assigning this nested task to a variable of type Task, which is allowed because the class Task<TResult> derives from the class Task. What happens then is that you lose the reference to the inner task, so you have no way of awaiting it. When you await this.backgroundTask you are awaiting the outer Task<Task>, but you can't get the result of the await operation, which is a Task, the inner Task, and await it. The inner task has become a fire-and-forget task.

await Task.Factory.StartNew(() = versus Task.Start; await Task;

StartNew is just a short hand for creating and starting a task. If you want to do something to the Task instance before you start it, use the constructor. If you just want to create and start the task immediately, use the short hand.

Documentation for StartNew says:

Calling StartNew is functionally equivalent to creating a task by
using one of its constructors, and then calling the Task.Start method
to schedule the task for execution.



Related Topics



Leave a reply



Submit