【发布时间】:2016-01-22 10:04:40
【问题描述】:
System.Data.SqlClient.SqlCommand中ExecuteNonQueryAsync()方法的实现如下:
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 绑定的方法?
【问题讨论】: