C# 使用Taskcompletion源创建无线程任务

C# 使用Taskcompletion源创建无线程任务,c#,multithreading,task-parallel-library,C#,Multithreading,Task Parallel Library,我在TPL中碰到了一个叫做TaskCompletionSource的主题,这是创建任务的方法之一,它允许开发人员设置结果、异常等,从而使您能够更好地控制任务。下面是一个使用TaskCompletionSource的示例 public static Task<int> RunAsyncFunction(Func<int> sampleFunction) { if (sampleFunction == null) thro

我在TPL中碰到了一个叫做TaskCompletionSource的主题,这是创建任务的方法之一,它允许开发人员设置结果、异常等,从而使您能够更好地控制任务。下面是一个使用TaskCompletionSource的示例

   public static Task<int> RunAsyncFunction(Func<int> sampleFunction)
    {
        if (sampleFunction == null)
            throw new NullReferenceException("Method cannot be null");

        var tcs = new TaskCompletionSource<int>();

        ThreadPool.QueueUserWorkItem(_ =>
        {
            try
            {
                int result = sampleFunction();
                tcs.SetResult(result);
            }
            catch (Exception ex)
            {
                tcs.SetException(ex);
            }
        });

        return tcs.Task;
    }
公共静态任务runasync函数(Func sampleFunction)
{
if(sampleFunction==null)
抛出新的NullReferenceException(“方法不能为null”);
var tcs=new TaskCompletionSource();
ThreadPool.QueueUserWorkItem(=>
{
尝试
{
int result=sampleFunction();
tcs.SetResult(结果);
}
捕获(例外情况除外)
{
tcs.SetException(ex);
}
});
返回tcs.Task;
}

但是,这不是真正的异步编程。它是使用多线程的异步编程。如何转换此示例以使其在单个线程而不是多个线程上运行?或者还有其他的例子吗?

为了实现异步,它需要在将来独立完成一些容量。这通常通过以下两种方式之一实现:

  • 通过套接字IO、文件IO、系统计时器等操作的回调(可能导致重新激活的某些外部源)
  • 第二个线程(可能是排队的工作池线程,如示例中所示)
如果您只有一个线程,并且没有外部回调,那么使用
Task
确实没有任何必要或意义。但是,您仍然可以通过立即执行计算并立即设置结果来公开它——或者更简单地说:使用
Task.FromResult

但是,您显示的代码实际上是异步的——或者更具体地说:您返回的
任务是异步的。它也许不是最好的用例,但它本身并没有什么问题——只是您的整个方法可以大大简化为:

return Task.Run(sampleFunction);
委员会:

对要在线程池上运行的指定工作进行排队,并返回该工作的任务或任务句柄


通常,如果我使用的是
TaskCompletionSource
,那是因为我编写的是基于IO回调的任务,而不是基于
ThreadPool
的任务<代码>任务。运行
对于大多数任务来说都很好。

要实现异步,它需要一些将来独立完成的容量。这通常通过以下两种方式之一实现:

  • 通过套接字IO、文件IO、系统计时器等操作的回调(可能导致重新激活的某些外部源)
  • 第二个线程(可能是排队的工作池线程,如示例中所示)
如果您只有一个线程,并且没有外部回调,那么使用
Task
确实没有任何必要或意义。但是,您仍然可以通过立即执行计算并立即设置结果来公开它——或者更简单地说:使用
Task.FromResult

但是,您显示的代码实际上是异步的——或者更具体地说:您返回的
任务是异步的。它也许不是最好的用例,但它本身并没有什么问题——只是您的整个方法可以大大简化为:

return Task.Run(sampleFunction);
委员会:

对要在线程池上运行的指定工作进行排队,并返回该工作的任务或任务句柄


通常,如果我使用的是
TaskCompletionSource
,那是因为我编写的是基于IO回调的任务,而不是基于
ThreadPool
的任务<代码>任务。运行
对于大多数情况都很好。

任务完成源代码不会使代码异步。它是一个实用工具,可以让其他人异步等待您的操作

您的操作本身需要是异步的。例如,如果它在一个较旧的范例中,比如BeginXXX/EndXXX


TaskCompletionSource主要用于将不同类型的异步编程转换为基于任务的异步编程

TaskCompletionSource不会使代码异步。它是一个实用工具,可以让其他人异步等待您的操作

您的操作本身需要是异步的。例如,如果它在一个较旧的范例中,比如BeginXXX/EndXXX


TaskCompletionSource主要用于将不同类型的异步编程转换为基于任务的异步编程

如果您有BeginXXX/EndXXX,您可以使用microsoft的utility methods@Gusdor sure包装该方法,因为它很常见。关键是,如果你需要实现这个方法,你可以使用TaskCuleTythOntRead。考虑我的评论,一个不知道的补充:-当然是Gusdor。如果愿意,您也可以在中编辑它。如果您有BeginXXX/EndXXX,您可以使用microsoft的utility methods@Gusdor sure包装该方法,因为它很常见。关键是,如果你需要实现这个方法,你可以使用TaskCuleTythOntRead。考虑我的评论,一个不知道的补充:-当然是Gusdor。如果愿意,您也可以在中编辑它。嗨,马克……那么TaskCompletionSource是创建无线程基本任务的唯一方法吗?@kyle在实现级别,是的;但是,如果您正在谈论的对象已经有了基于
任务的异步API,那么您通常可以使用
异步
/
等待
通过延续来组成更复杂的逻辑;然后编译器会为您提供大部分细节。嗨,马克……那么TaskCompletionSource是创建无线程基本任务的唯一方法吗?@kyle在实现级别,是的;但是,如果您正在谈论的对象已经有了基于
任务的异步API,那么您通常可以使用
异步
/
等待
通过延续来组成更复杂的逻辑;然后,编译器将为您提供大部分详细信息。