IO Async方法中的TaskCompletionSource用法

时间:2016-01-22 10:04:40

标签: c# taskcompletionsource

test_methodExecuteNonQueryAsync()方法的实施如下:

System.Data.SqlClient.SqlCommand

我将其概括为:

  
      
  1. 创建 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; }
  2.   
  3. 使用TaskCompletionSource<int> source = new TaskCompletionSource<int>();创建一个新任务,使用APM&#34;开始/结束&#34; API
  4.   
  5. 任务完成时调用Task<int>.Factory.FromAsync
  6.   
  7. 返回source.SetResult()
  8.   

在此处使用source.Task以及为什么不直接返回TaskCompletionSource创建的任务有什么意义?此任务还包含结果和异常(如果有)。

在Nutshell书中的C#中,在 Asynchronous Programming and Continuations 部分中,它指出:

  

在编写延迟时,我们   使用TaskCompletionSource,这是实现“底层”的标准方法   I / O绑定的异步方法。

     

对于计算绑定方法,我们使用Task.Run来启动线程绑定并发。   只需将任务返回给调用者,我们就创建了一个异步方法。

为什么使用Task<int>.Factory.FromAsync()可以实现计算绑定方法,而不是I / O绑定方法?

1 个答案:

答案 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方法。