【问题标题】:How to check that all tasks have been properly completed?如何检查所有任务是否已正确完成?
【发布时间】:2012-09-03 13:28:10
【问题描述】:

我的代码中有以下几行:

    var taskA = Task.Factory.StartNew(WorkA);
    var taskB = Task.Factory.StartNew(WorkB);
    var allTasks = new[] { taskA, taskB };

    Task.Factory.ContinueWhenAll(allTasks, tasks => FinalWork(), TaskContinuationOptions.OnlyOnRanToCompletion);

但是当我运行它时,我得到以下错误:

对于多任务的延续,排除特定的延续种类是无效的。

这是由选项 TaskContinuationOptions.OnlyOnRanToCompletion 引起的。

我的问题是如何检查所有任务是否已正常完成工作(所有任务状态都是RanToCompletion)然后执行FinalWork()? 与此同时,应用程序执行其他任务。

【问题讨论】:

  • 如果某些Tasks 失败了,你想做什么?
  • 如果某些Tasks 失败了,什么也不应该做。

标签: c# multithreading .net-4.0 task task-parallel-library


【解决方案1】:

根据@Peter Ritchie 和@Ben McDougall 的回答,我找到了解决方案。我通过删除冗余变量 tasksTaskContinuationOptions.OnlyOnRanToCompletion 修改了我的代码

var taskA = Task.Factory.StartNew(WorkA);
var taskB = Task.Factory.StartNew(WorkB);
var allTasks = new[] { taskA, taskB };
Task.Factory.ContinueWhenAll(allTasks, FinalWork);

FinalWork 在哪里:

private static void FinalWork(Task[] tasks)
{
   if (tasks.All(t => t.Status == TaskStatus.RanToCompletion))
   {
        // do "some work"
   }
}

如果所有tasks 的状态为RanToCompletion“一些工作” 将完成。它会在所有任务完成后立即执行,不会阻塞主任务。 如果我取消了至少一项任务,则什么都不会做。

您也可以这样做,

var taskA = Task.Factory.StartNew(WorkA);
var taskB = Task.Factory.StartNew(WorkB);
var allTasks = new[] { taskA, taskB };
var continuedTask = Task.WhenAll(allTasks).ContinueWith((antecedent) => { /*Do Work*/ }, TaskContinuationOptions.OnlyOnRanToCompletion));

【讨论】:

  • 替代方案似乎是要走的路——甚至the docs 建议它。
【解决方案2】:

您没有提供任何代码来处理任何运行到完成的任务(您的 tasks 变量被忽略)。如果您只是删除TaskContinuationOptions.OnlyOnRanToCompletion,您会得到相同的结果。即如果您可以ContinueWhenAllTaskContinuationOptions.OnlyOnRanToCompletion 一起使用,则在所有任务完成或失败之前不会调用您的延续。如果你只对完成的任务不做任何事情,那和Task.Factory.ContinueWhenAll(allTasks, tasks => FinalWork());是一样的

如果您想做更具体的事情,请提供详细信息,以便有人可以帮助您。

【讨论】:

  • 是的,你是对的。现在我看到变量tasks 是多余的。所有关于任务状态的信息都可以通过变量allTasks传递给函数。
【解决方案3】:

回答你提出的实际问题:

我的问题是如何检查所有任务是否已正常完成工作(所有任务状态均为 RanToCompletion)然后执行 FinalWork()?与此同时,应用程序执行其他任务。

至少这是我读到的问题,请检查以下代码:

    var taskA = Task.Factory.StartNew(WorkA);
    var taskB = Task.Factory.StartNew(WorkB);
    var allTasks = new[] { taskA, taskB };

    taskA.Wait();
    taskB.Wait();

    if (taskA.Status == TaskStatus.RanToCompletion && taskB.Status == TaskStatus.RanToCompletion)
        Task.Factory.ContinueWhenAll(allTasks, tasks => FinalWork());
    else
        //do something

如果你是认真的,你实际上是用你的问题自己回答了这个问题。

【讨论】:

  • 感谢您的回答。不幸的是,此解决方案使用Task.Wait的方法阻塞了主要任务
  • @Zen 我在任务声明和等待之间添加了一些任务,它们执行得很好,我们的锁定稍后会再次查看您的问题。
  • @Zen:我添加了一个新类并包含一个线程,一切都很好。什么都没有锁定,一切都在顺利进行。我需要有关您的问题的更多信息,因为到目前为止我没有任何困难。基本上添加了一个类,它在构造函数中启动一个线程并在任务之前添加它:code var taskC = Task.Factory.StartNew(WorkC); JustAnotherThread jt = new JustAnotherThread(); var taskA = Task.Factory.StartNew(WorkA);code
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
  • 2018-04-18
  • 2014-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多