Създавам приложение .NET 4.0, което използва ADO.NET, така че не мога да използвам async/await. Не искам решение за това, но искам да знам коя от следните реализации е най-добра и защо. Моите модулни тестове преминават и за трите реализации, но искам да знам разликата между тези три.
#1 Задачи за влагане
При първото си изпълнение обгръщам задача в друга задача. Мисля, че завъртането на две задачи е лошо за производителността, но не съм сигурен.
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 Използване на TaskCompletionSource
След това се опитах да опаковам резултата в TaskCompletionSource
, така че имам само една задача.
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 връщане на Задача директно
Последното ми решение е директно да върна задачата, която създадох, вместо да я обвивам.
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);
}
Така че основно въпросът ми е:
Каква опция да използвам или има ли по-добър начин да направя това?