取消任务并等待它完成

时间:2013-02-14 19:02:29

标签: c# task-parallel-library

我有一个耗时的任务,我需要在一个单独的线程中运行,以避免锁定GUI线程。随着此任务的进行,它会更新特定的GUI控件。

问题是用户可能在任务结束之前移动到GUI的另一部分,在这种情况下,我必须:

  1. 取消正在进行的任务(如果已激活)
  2. 等到它完成取消:这是至关重要的,因为耗时任务的目标是更新特定控件。如果多个线程一次尝试这样做,事情可能会变得混乱。
  3. 从头开始执行任务
  4. 对于一个具体的例子,假设表单有两个部分:一个用于导航目录树,另一个用于显示缩略图。当用户导航到另一个目录时,需要刷新缩略图。

    首先我想到使用BackgroundWorkerAutoResetEvent等待取消,但我必须弄乱一些东西,因为我在取消时遇到了僵局。然后我读到了TPL,它应该取代BGW和更原始的机制。

    使用TPL可以轻松完成吗?

1 个答案:

答案 0 :(得分:22)

有几点需要注意:

  • 您可以从CancellationToken

  • 获得CancellationTokenSource
  • 任务取消是合作操作:如果您的任务未定期检查CancellationToken.IsCancellationRequested属性,则尝试取消任务的次数无关紧要,它会愉快地流失。

那些事情说,这是一般的想法:

void Main()
{
    var tokenSource = new CancellationTokenSource();
    var myTask = Task.Factory
        .StartNew(() => DoWork(tokenSource.Token), tokenSource.Token);

    Thread.Sleep(1000);

    // ok, let's cancel it (well, let's "request it be cancelled")
    tokenSource.Cancel();

    // wait for the task to "finish"
    myTask.Wait();
}

public void DoWork(CancellationToken token)
{
    while(!token.IsCancellationRequested)
    {
        // Do useful stuff here
        Console.WriteLine("Working!");
        Thread.Sleep(100);
    }
}