Task.Factory.ContinueWhenAll调用的适当结构

时间:2012-03-02 21:36:48

标签: .net task-parallel-library asp.net-web-api

我想确保我正在使用ContinueWhenAll。我有许多调用将运行异步,然后我想完成其他任务成功完成后我完成最后一个任务,然后我对结果做一些计算,看看我是否应该停止处理并返回一个禁止的HTTP结果。我不确定的是最后一行是否真的会等待所有其他任务完成,或者我是否需要以不同方式构建它。如果是这样,那么最后一行应该如何构造,以便只有在我超过if的评估时才调用它(getPlatformTask.Result ...

// run some tasks and then gather them here
Task.Factory.ContinueWhenAll(new Task[]{ getPlatformTask, getUserTask },
    (tasks) =>
    {
        Task.WaitAll(tasks);

        if (getPlatformTask.Result == null || getUserTask.Result == null)
        {
           return Task<HttpResponseMessage>.Factory.StartNew(() =>
           {
              return new HttpResponseMessage(HttpStatusCode.Forbidden);
           });
        }
    });

// will this line below get called before the inner task above completes?   
return base.SendAsync(request, cancellationToken);       

1 个答案:

答案 0 :(得分:3)

如果要在完成所有任务之前阻止当前线程,则只需使用Task.WaitAll(),无需使用延续任务。但请记住,被阻塞的线程是一个除了耗尽资源(如内存)之外什么都不做的线程。阻止线程通常更容易,但执行效率的方式效率较低。

代码可能如下所示:

// run the tasks

Task.WaitAll(getPlatformTask, getUserTask);

// process the results

return base.SendAsync(request, cancellationToken);

不,在您的版本中,最后一行可以(并且很可能会)在所有任务完成之前执行。 ContinueWhenAll()没有阻止,这就是它的全部要点。

编辑:我刚刚意识到您的方法会返回Task。因此,您实际上不必阻止该线程,而是可以返回在完成所有工作后完成的Task。它看起来像这样:

// run the tasks

var result = Task.Factory.ContinueWhenAll(
    new[] { getPlatformTask, getUserTask },
    _ =>
    {
        // process the results

        return base.SendAsync(request, cancellationToken);
    });

return result.Unwrap();

此处resultTask<Task<HttpResponseMessage>>,但您只需要Task<HttpResponseMessage>。为此,您可以使用the Unwrap() method