【问题标题】:what is the correct way to cancel multiple tasks in c#在c#中取消多个任务的正确方法是什么
【发布时间】:2011-09-16 21:56:06
【问题描述】:

我有一个生成 4 个任务的按钮。同一个按钮变为取消按钮,单击该按钮应取消所有 4 个任务。我是否应该将相同的取消令牌传递给所有 4 个任务并让它们轮询 IsCancelRequested 的相同令牌?在阅读了createlinkedtokensource 上的 msdn 文档后,我感到很困惑。这通常是如何完成的?谢谢

更新:Task.WaitAll() 等待所有任务完成执行。同样,一旦共享取消令牌源设置为取消,如何知道所有任务都已取消

【问题讨论】:

  • 我更新了我的答案以反映您的更新。

标签: c# c#-4.0 task-parallel-library task pfx


【解决方案1】:

是的,您所说的使用单个 CancellationToken 是正确的。您可以创建一个 CancellationTokenSource 并将其 CancellationToken 用于所有任务。您的任务应定期检查令牌是否取消。

例如:

const int NUM_TASKS = 4;

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;

Task[] tasks = new Task[NUM_TASKS];
for (int i = 0; i < NUM_TASKS; i++)
{
    tasks[i] = Task.Factory.StartNew(() =>
    {
        while (true)
        {
            Thread.Sleep(1000);
            if (ct.IsCancellationRequested)
                break;
        }
    }, ct);
}

Task.WaitAll(tasks);

您的按钮可以调用cts.Cancel(); 取消任务。

问题更新更新:

有几种方法可以满足您的要求。一种方法是使用ct.IsCancellationRequested 来检查取消而不抛出,然后让您的任务完成。然后Task.WaitAll(tasks) 将在所有任务被取消后完成。

我已更新代码以反映该更改。

【讨论】:

  • 这将阻止 UI 最多 4 秒
  • 这是一个等待所有任务的示例,每个任务每秒都会检查是否完成。它没有在 GUI 应用程序的完整上下文中给出。
  • 我同意@Matt 的回答。但我想指出var task = Task.WhenAll(tasks); 更容易管理。 WaitAll() 将抛出一个异常,并且会抛出一个丑陋的 AggregateException - 如果任何任务出错或被取消。请在MSDN 上查看此方法的定义行为。在绝大多数情况下,这种行为意味着您需要做的就是检查返回的任务(来自WhenAll())状态
  • @Matt,感谢您的解决方案。上面的代码我尝试了 5 个或更多任务,但它不起作用。你能告诉我我可以打电话给 cts.Cancel();在 Task.WaitAll 之前。
【解决方案2】:

是的,如果这是您的意图,您应该传递相同的令牌并使用它一次性取消所有任务。

【讨论】:

    【解决方案3】:

    使用BackroundWorker类,设置属性WorkerSupportsCancellation,调用RunWorkerAsync()启动任务,使用CancelAsync()停止任务p>

    您无需将代码与 UI 同步。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多