Asynchronous TaskCompletionSource-尝试了解无线程异步工作

Asynchronous TaskCompletionSource-尝试了解无线程异步工作,asynchronous,task-parallel-library,Asynchronous,Task Parallel Library,我试图理解TaskCompletionSource的目的及其与异步/无线程工作的关系。我想我有大致的想法,但我想确保我的理解是正确的 我首先开始研究任务并行库(TPL),想知道是否有一种好方法可以创建自己的无线程/异步工作(比如说,您正试图提高ASP.NET站点的可伸缩性),另外,对TPL的理解看起来在未来非常重要(async/wait)。这让我找到了TaskCompletionSource 从我的理解来看,将TaskCompletionSource添加到一个类中并不像使编码异步那样有效;如果您

我试图理解
TaskCompletionSource
的目的及其与异步/无线程工作的关系。我想我有大致的想法,但我想确保我的理解是正确的


我首先开始研究任务并行库(TPL),想知道是否有一种好方法可以创建自己的无线程/异步工作(比如说,您正试图提高ASP.NET站点的可伸缩性),另外,对TPL的理解看起来在未来非常重要(
async
/
wait
)。这让我找到了
TaskCompletionSource


从我的理解来看,将
TaskCompletionSource
添加到一个类中并不像使编码异步那样有效;如果您仍在执行同步代码,则对代码的调用将被阻止。我认为这甚至适用于微软的API。例如,假设在
WebClient
类的
downloadstringtasksync
off中,他们最初执行的任何设置/同步代码都将被阻止。您正在执行的代码必须在某个线程上运行,或者在当前线程上运行,或者必须派生一个新线程


因此,当您从Microsoft调用其他
async
调用时,您可以在自己的代码中使用
TaskCompletionSource
,这样您的类的客户端就不必为您的类创建一个新线程来阻止它

不确定微软如何在内部实现他们的异步API。例如,在.NET4.5的
SqlDataReader
中有一个新的
async
方法。我知道有IO完成端口。我认为这是一个较低级别的抽象(C++?),大多数C#开发人员可能不会使用。不确定IO完成端口是否适用于数据库或网络调用(HTTP),或者是否仅用于文件IO


所以问题是,我的理解正确吗?是否有某些东西我表示不正确?

TaskCompletionSource
用于创建不执行代码的
Task
对象

微软新的异步API经常使用它们——任何时候都有基于I/O的异步操作(或其他非基于CPU的异步操作,如超时)。此外,您编写的任何
异步任务
方法都将使用TCS来完成返回的
任务

我有一篇博文讨论了创建
Task
实例的不同方法。它是从
async
/
await
透视图(不是TPL透视图)编写的,但它仍然适用于这里

另请参见Stephen Toub的精彩帖子:


  • (使用
    TaskCompletionSource
    wait
    anything)

  • (使用
    TaskCompletionSource
    创建
    Begin
    /
    End

    • 我喜欢中提供的解释

      (抱歉,该链接目前可能已断开)

      前两段如下

      我们已经了解了Task.Run如何创建一个在服务器上运行委托的任务 池(或非池)线程。创建任务的另一种方法是使用 TaskCompletionSource

      TaskCompletionSource允许您通过执行以下操作来创建任务: 一段时间后开始和结束。它的工作原理是给你一个“奴隶” 通过指示操作完成的时间手动驱动的任务 或错误。这是I/O绑定工作的理想选择:您将获得所有好处 任务(具有传播返回值、异常、, 和continuations),而不会在 手术

      要使用TaskCompletionSource,只需实例化该类。信息技术 公开一个任务属性,该属性返回可等待的任务 并像处理任何其他任务一样附加continuations。任务,, 但是,完全由TaskCompletionSource对象通过 以下方法:

      公共类TaskCompletionSource
      { 
      公共无效设置结果(TResult结果);
      公共无效设置例外(例外);
      公共无效设置已取消();
      公共bool TrySetResult(TResult结果);
      公共bool TrySetException(异常);
      公共bool TrySetCanceled();
      ... 
      }
      
      调用这些方法中的任何一个都会向任务发出信号,并将其放入 完成、故障或取消状态(我们将在 “取消”一节)。你应该调用其中一种方法 仅一次:如果再次调用,则SetResult、SetException或setCancelled 将引发异常,而Try*方法返回false

      以下示例在等待五秒钟后打印42:

      var tcs=new TaskCompletionSource();
      新线程(()=>{
      睡眠(5000);
      tcs.SetResult(42);
      })    
      .Start();
      Task Task=tcs.Task;//我们的“奴隶”任务。
      Console.WriteLine(task.Result);//42
      
      其他有趣的引语

      TaskCompletionSource的真正威力在于创建不需要的任务 把线捆起来

      。。后来

      在没有线程的情况下使用TaskCompletionSource意味着 仅当连续性开始时(5秒后)才接通。我们 可以通过一次启动10000个这样的操作来证明这一点 没有错误或过度的资源消耗:


      如果我的理解是正确的…不确定是否正确,但我对内部的理解是否正确?任何异步方法(当然)都有一个用于启动异步操作的同步部分。IIRC,IOCP可用于任何类型的基于
      句柄的数据传输,并且(今天)将IOCP操作包装在
      开始
      /
      结束
      中,并将其包装在
      任务
      中的
      异步
      方法中(使用
      任务完成源
      )并不少见.我也在努力了解Ta的用法
      public class TaskCompletionSource<TResult> 
      { 
       public void SetResult(TResult result); 
       public void SetException (Exception exception); 
      
       public void SetCanceled();   
       public bool TrySetResult (TResult result); 
       public bool TrySetException (Exception exception); 
       public bool TrySetCanceled();
       ... 
      }
      
      var tcs = new TaskCompletionSource<int>();
      new Thread (() =>     {
                             Thread.Sleep (5000); 
                             tcs.SetResult (42); 
                            })    
                 .Start();   
      Task<int> task = tcs.Task;    // Our "slave" task. 
      Console.WriteLine(task.Result);  // 42