Я создаю приложение .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 возвращает Task напрямую
Мое окончательное решение состоит в том, чтобы напрямую вернуть задачу, которую я создал, а не обертывать ее.
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);
}
Итак, в основном мой вопрос:
Какой вариант я должен использовать или есть лучший способ сделать это?