取消任务并等待它完成

取消任务并等待它完成

问题描述:

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

美中不足的是,面前的任务是在用户可能移动到图形用户界面的另一部分,并且在这种情况下,我必须:

  1. 取消正在进行的任务(如果它是活动)
  2. 等到它完成取消:这是至关重要的,因为耗时的任务的目标是更新特定的控件。如果不止一个线程试图立即执行,事情可能会变得混乱。
  3. 启动从头

任务对于一个具体的例子,设想的形式主要有两个部分:一是在您浏览目录树,和另一个在那里你显示缩略图。当用户导航到另一个目录时,需要刷新缩略图。

首先我想到使用BackgroundWorkerAutoResetEvent来等待取消,但是我一定弄错了一些东西,因为取消时我被锁定了。然后我读了关于TPL,它应该取代BGW和更原始的机制。

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

有几件事情需要注意:

  • 可以从CancellationTokenSource

  • 任务取消获得CancellationToken合作行动:如果你的任务没有定期检查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); 
    } 
} 
+0

是否还好只是一次创建令牌源及其令牌传递到'StartNew'每一次? – 2013-02-15 12:49:09

+0

把它想象成一个小孩的两个罐子放在一个串上(好吧,一个给N罐头:你有一端,所有开始的任务都可以,你一边喊“取消”,所有分享令牌的人都会听到它。 – JerKimball 2013-02-15 15:27:17

+1

@dario_ramos我相信你的评论中的问题是在评论[这里](http://*.com/questions/14896248/deadlock-when-waiting-for-task-to-finish)中回答的,但为了完整性'因此,答案是否定的 - 'CancellationTokenSource'不能被重置和取消;如果你要求取消一个,那么如果你想再次取消,你必须用一个新的取代它 – shambulator 2013-02-16 12:05:36