Should I transfer the task to another task or should I just return the created task?

I am creating a .NET 4.0 application that uses ADO.NET, so I cannot use async / wait. I don't want a solution for this, but I really want to know which of the following implementations is best and why. My unit tests pass for all three implementations, but I want to know the difference between the three.

# 1 Attachment Tasks

In my first implementation, I transfer the task to another task. I think deploying two tasks is bad for performance, but I'm not sure.

public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken) { return Task.Factory.StartNew(() => { var sqlCommand = CheckIfSqlCommand(dbCommand); PrepareExecuteReader(dbCommand); return Task<IDataReader> .Factory .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null) .Result; }, cancellationToken); } 

# 2 Using TaskCompletionSource

Then I tried to wrap the result in a TaskCompletionSource , so I only have one task.

 public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken) { var taskCompletionSource = new TaskCompletionSource<IDataReader>(); var sqlCommand = CheckIfSqlCommand(dbCommand); PrepareExecuteReader(dbCommand); var reader = Task<IDataReader> .Factory .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null) .Result; taskCompletionSource.SetResult(reader); return taskCompletionSource.Task; } 

# 3 return directly to the task

My final solution is to directly return the created task instead of packing it.

 public virtual Task<IDataReader> ExecuteReaderAsync(IDbCommand dbCommand, CancellationToken cancellationToken) { var sqlCommand = CheckIfSqlCommand(dbCommand); PrepareExecuteReader(dbCommand); return Task<IDataReader> .Factory .FromAsync(sqlCommand.BeginExecuteReader, sqlCommand.EndExecuteReader, null); } 

So basically my question is:

Which option to use or is there a better way to do this?

+5
c # task-parallel-library
Feb 27 '14 at 9:05
source share
1 answer

Your number 3 is the best. The first two complicate the situation for no reason.

1 potentially adds another thread only for asynchronous launch of CheckIfSqlCommand() and PrepareExecuteReader() . It may be what you wanted, but they do not sound like teams that take a lot of time.

2 links .Result task, which will be blocked until the task is completed, therefore the whole purpose of using the tasks wins.

+3
Feb 27 '14 at 9:10
source share



All Articles