14

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

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

  1. 取消正在进行的任务(如果它处于活动状态)
  2. 等到它完成取消:这是至关重要的,因为耗时任务的目标是更新特定控件。如果多个线程同时尝试执行此操作,事情可能会变得一团糟。
  3. 从头开始启动任务

举一个具体的例子,假设表单有两个部分:一个是导航目录树的地方,另一个是显示缩略图的地方。当用户导航到另一个目录时,缩略图需要刷新。

首先我想使用 aBackgroundWorker和 anAutoResetEvent来等待取消,但我一定搞砸了,因为取消时我陷入了僵局。然后我读到了 TPL,它应该取代 BGW 和更原始的机制。

这可以使用 TPL 轻松完成吗?

4

1 回答 1

28

需要注意的几点:

  • 你可以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);
    }
}
于 2013-02-14T21:37:13.163 回答