Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task.Factory.StartNew vs Task.Factory.FromAsync

Let's suppose we have a I/O bound method (such as a method making DB calls). This method can be run both in synchronously and asynchronously. That is,

  1. Sync:

    IOMethod() 
  2. Async:

    BeginIOMethod() EndIOMethod() 

Then when we execute the method in different ways as shown below, what's the performance difference in terms of the resource utilization?

  1. var task = Task.Factory.StartNew(() => { IOMethod(); }); task.Wait(); 
  2. var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... ); task.Wait(); 
like image 618
soleiljy Avatar asked Jul 02 '13 17:07

soleiljy


People also ask

What is the difference between task run and task factory StartNew?

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!

What does task factory StartNew do?

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.

What is the use of task factory in C#?

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.

What is difference between task and thread in C#?

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.


2 Answers

var task = Task.Factory.StartNew(() => { IOMethod(); }); task.Wait(); 

This will block a thread pool thread while IOMethod() is executing and also block your current thread because of the Wait(). Total blocked threads: 2.


var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... ); task.Wait(); 

This will (most likely) perform the operation asynchronously without using a thread, but it will block the current thread because of the Wait(). Total blocked threads: 1.


IOMethod(); 

This will block the current thread while IOMethod() is executing. Total blocked threads: 1.

If you need to block the current thread, or if blocking it is okay for you, then you should use this, because trying to use TPL won't actually give you anything.


var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... ); await task; 

This will perform the operation asynchronously without using a thread, and it will also wait for the operation to complete asynchronously, thanks to await. Total blocked threads: 0.

This is what you should use if you want to take advantage of asynchrony and you can use C# 5.0.


var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... ); task.ContinueWith(() => /* rest of the method here */); 

This will perform the operation asynchronously without using a thread, and it will also wait for the operation to complete asynchronously, thanks to ContinueWith(). Total blocked threads: 0.

This is what you should use if you want to take advantage of asynchrony and you can't use C# 5.0.

like image 195
svick Avatar answered Sep 23 '22 01:09

svick


(1) will (likely) cause the .NET thread pool to process your Task.

(2) will use whatever mechanism your BeginIOMethod / EndIOMethod pair natively uses to handle the asynchronous part, which may or may not involve the .NET thread pool.

For example, if your BeginIOMethod is sending a TCP message across the internet, and at a later time the recipient is going to send you a TCP message in response (received by EndIOMethod), then the asynchronous nature of the operation is not being provided by the .NET thread pool. The TCP library being used is providing the asynchronous part.

This can be accomplished by using the TaskCompletionSource class. Task.Factory.FromAsync can create a TaskCompletionSource<T>, return its Task<T>, then use EndIOMethod as a trigger to place the Result into the Task<T> that was returned form Task.Factory.FromAsync at the time of calling.

What's the performance difference in terms of the resource utilization?

The difference between (1) and (2) is primarily just whether the .NET thread pool is going to have its workload added to or not. In general, the correct thing to do is to choose Task.Factory.FromAsync if you only have a Begin... / End... pair and Task.Factory.StartNew otherwise.


If you're using C# 5.0, then you should be using the non-blocking await task; instead of task.Wait();. (See svick's answer.)

like image 27
Timothy Shields Avatar answered Sep 24 '22 01:09

Timothy Shields