Реализация метода ExecuteNonQueryAsync()
в System.Data.SqlClient.SqlCommand
выглядит следующим образом:TaskCompletionSource использование методов IO Async
public override Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken) {
Bid.CorrelationTrace("<sc.SqlCommand.ExecuteNonQueryAsync|API|Correlation> ObjectID%d#, ActivityID %ls\n", ObjectID);
SqlConnection.ExecutePermission.Demand();
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
CancellationTokenRegistration registration = new CancellationTokenRegistration();
if (cancellationToken.CanBeCanceled) {
if (cancellationToken.IsCancellationRequested) {
source.SetCanceled();
return source.Task;
}
registration = cancellationToken.Register(CancelIgnoreFailure);
}
Task<int> returnedTask = source.Task;
try {
RegisterForConnectionCloseNotification(ref returnedTask);
Task<int>.Factory.FromAsync(BeginExecuteNonQueryAsync, EndExecuteNonQueryAsync, null).ContinueWith((t) => {
registration.Dispose();
if (t.IsFaulted) {
Exception e = t.Exception.InnerException;
source.SetException(e);
}
else {
if (t.IsCanceled) {
source.SetCanceled();
}
else {
source.SetResult(t.Result);
}
}
}, TaskScheduler.Default);
}
catch (Exception e) {
source.SetException(e);
}
return returnedTask;
}
который я хотел бы резюмировать следующим образом:
- Создать
TaskCompletionSource<int> source = new TaskCompletionSource<int>();
- Создать новый с использованием
Task<int>.Factory.FromAsync
, используя API APM «Begin/End»- Вызов
source.SetResult()
, когда задача завершается.- Вернуться
source.Task
Какой смысл использовать TaskCompletionSource
здесь и почему бы не вернуть задачу, созданную Task<int>.Factory.FromAsync()
напрямую? У этой задачи также есть результат и исключение (если есть).
В C# в книге кратко, в асинхронном программировании и продолжениях раздела, в нем говорится:
При написании задержки, мы использовал TaskCompletionSource, который является стандартным способом реализации «нижнего уровня " Асинхронные методы с привязкой к вводу/выводу.
Для методов, основанных на вычислении, мы используем Task.Run, чтобы инициировать параллелизм, связанный с потоком. Просто возвращая задачу вызывающему, мы создаем асинхронный метод.
Почему методы, связанные с вычислением, могут быть реализованы с использованием Task.Run()
, но не связаны с методами ввода-вывода?
Могу ли я сказать, что использование TaskCompletionSource на самом деле должно унифицировать вывод метода, поэтому исключение сглаживается, результат устанавливается и т. Д. В этом случае многопроцессорная механика внутри метода может быть чем угодно. – Helic
_ «механизм резьбы внутри метода может быть любым» _ - до тех пор, пока метод работает асинхронно, да. Использование TCS здесь позволяет публичному методу быть _abstraction_ того, что на самом деле происходит внутри, гарантируя, что вызывающий абонент не зависит от конкретных сведений о реализации (например, хороших практик реализации). –