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,
Sync:
IOMethod()
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?
var task = Task.Factory.StartNew(() => { IOMethod(); }); task.Wait();
var task = Task.Factory.FromAsync(BeginIOMethod, EndIOMethod, ... ); task.Wait();
(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 byEndIOMethod
), 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 aTaskCompletionSource<T>
, return itsTask<T>
, then useEndIOMethod
as a trigger to place theResult
into theTask<T>
that was returned formTask.Factory.FromAsync
at the time of calling.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 aBegin...
/End...
pair andTask.Factory.StartNew
otherwise.If you're using C# 5.0, then you should be using the non-blocking
await task;
instead oftask.Wait();
. (See svick's answer.)This will block a thread pool thread while
IOMethod()
is executing and also block your current thread because of theWait()
. Total blocked threads: 2.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.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.
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.
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.