ExecuteNonQueryAsync()
方法的实现System.Data.SqlClient.SqlCommand
如下:
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
使用 APM "Begin/End" API创建一个新任务source.SetResult()
任务完成时调用。- 返回
source.Task
在这里使用有什么意义,TaskCompletionSource
为什么不直接返回由创建的任务Task<int>.Factory.FromAsync()
?此任务还包装了结果和异常(如果有)。
在 C# in a Nutshell book 的Asynchronous Programming and Continuations部分中,它指出:
在编写延迟时,我们使用了 TaskCompletionSource,这是实现“底层”I/O 绑定异步方法的标准方法。
对于计算绑定方法,我们使用 Task.Run 来启动线程绑定并发。只需将任务返回给调用者,我们就创建了一个异步方法。
为什么计算绑定的方法可以使用 实现Task.Run()
,而不是 I/O 绑定的方法?