【问题标题】:Cancelling and restarting a task取消和重新启动任务
【发布时间】:2015-09-03 14:19:52
【问题描述】:

我已经阅读了一些关于此的文章,但我目前一无所知。我正在开发一个应用程序,其中有一个位于表单上的 TabControl。当用户单击标签页时,我希望后台进程从 UI 线程中运行(因为该进程可能需要几分钟)。这很好,但是如果用户选择不同的选项卡,我希望取消任何当前活动的任务,并注意转到新选项卡。

private void ParentTabControl_SelectedIndexChanged(object sender, EventArgs e)
    {
        Task testTask;
        CancellationTokenSource testSource = new CancellationTokenSource();
        CancellationToken testToken = testSource.Token;

        switch (ParentTabControl.SelectedIndex)
        {
            case 0:
                updateSummaryTab();
                break;
            case 1:
                testTask = Task.Run(() =>
                    {
                        updateTabOne();
                    }, testToken);
                break;
            case 2:
                updateTabTwo();
                break;
        }
    }

如果我将 testSource 设置为取消,那么这将不再可用(尽管我知道我需要使用某种令牌)。我以前为每个选项卡使用不同的 BackgroundWorker,并简单地检查它的 IsBusy 属性,但我认为使用单个回收的 Task 可能是更好的选择。

【问题讨论】:

  • 您遇到了什么具体问题?似乎您所要做的就是在切换标签时取消任何未完成的工作并开始新工作。
  • 我遇到的问题是当我使用 CancellationToken 取消任务时,新任务无法启动(大概是因为它使用了相同的令牌,现在设置为已取消)

标签: c# multithreading task-parallel-library task


【解决方案1】:

我遇到的问题是当我使用 CancellationToken 取消任务时,新任务无法启动

为您开始的每一轮工作创建一个新的 CTS(和 CT)。您需要将最后一轮的 CTS 存储在字段中。那么,开始新的工作就是:

if(cts != null) cts.Cancel();
cts = new ...;
StartWork(cts.Token);

请注意,取消正在运行的任务是合作的,将令牌传递给 Task.Run 不会执行任何操作,因为它不会停止已经运行的任务。

【讨论】:

  • 我有一种感觉,我必须回收 CancellationTokenSource,我只是想不通如何。如果在任务运行时将令牌传递给任务不会取消它(但使用 cts.Cancel() 会),那么使用令牌是否有任何意义?
  • 您需要将令牌传递到“StartWork”并在那里使用它。轮询它或将其传递给 IO 方法。
  • 啊,运行中的Tasks好像不能取消了。你会建议我在这种情况下重新使用 BackgroundWorker 吗?
  • 没有。 BackgroundWorker 已过时。也不能取消。你知道你可以以合作的方式取消工作吗?将令牌传递给 IO 方法等。它们可以被取消。
  • 这是我第一次听说合作取消工作;好像我还有一些阅读要做。感谢您的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-09
  • 2012-09-19
  • 1970-01-01
  • 2013-09-30
  • 1970-01-01
  • 2018-02-22
相关资源
最近更新 更多