test_method
中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>();
创建一个新任务,使用APM&#34;开始/结束&#34; API- 任务完成时调用
Task<int>.Factory.FromAsync
。- 返回
醇>source.SetResult()
在此处使用source.Task
以及为什么不直接返回TaskCompletionSource
创建的任务有什么意义?此任务还包含结果和异常(如果有)。
在Nutshell书中的C#中,在 Asynchronous Programming and Continuations 部分中,它指出:
在编写延迟时,我们 使用TaskCompletionSource,这是实现“底层”的标准方法 I / O绑定的异步方法。
对于计算绑定方法,我们使用Task.Run来启动线程绑定并发。 只需将任务返回给调用者,我们就创建了一个异步方法。
为什么使用Task<int>.Factory.FromAsync()
可以实现计算绑定方法,而不是I / O绑定方法?
答案 0 :(得分:3)
请注意,对于明确的答案,您必须询问代码的作者。除此之外,我们只能推测。但是,我认为以合理的准确度做出一些推论是合理的......
在这里使用TaskCompletionSource有什么意义,为什么不直接返回Task.Factory.FromAsync()创建的任务?
在这种情况下,在我看来,主要原因是允许实现在任务实际完成之前取消注册已注册的回调CancelIgnoreFailure()
。这可以确保在客户端代码收到完成通知时,API本身已完全从操作中清除。
次要原因可能只是提供完整的抽象。即不允许底层实现的任何到&#34;泄漏&#34;从方法中,以Task
对象的形式,调用者可能会检查或(更糟)操纵,干扰任务的正确和可靠操作。
为什么使用
Task.Run()
可以实现计算绑定方法,而不是I / O绑定方法?
您可以使用Task.Run()
实现I / O绑定操作,但为什么会这样做?这样做会将一个线程提交给操作,对于一个不需要线程的操作来说,这是一种浪费。
I / O绑定操作通常支持来自I / O完成端口和IOCP线程池(其线程处理任意大量IOCP的完成),因此简单地使用现有的异步更高效I / O API,而不是使用Task.Run()
来调用同步I / O方法。