2013-02-14 20 views
10

GUIスレッドのロックを避けるために別のスレッドで実行するのに時間がかかる作業があります。このタスクが進行すると、特定のGUIコントロールが更新されます。 (それがアクティブな場合)タスクをキャンセルして終了するまで待ちます

  1. は、現在進行中のタスクをキャンセル
  2. キャッチは、タスクが終わる前に、ユーザーがGUIの別の部分に移動する可能性があり、その場合には、私が持っているということです

  3. キャンセルが完了するまでお待ちください:時間のかかる作業の目的は特定のコントロールを更新することであるため、これは重要です。一度に複数のスレッドがそれをやろうとすると、物事が乱れることがあります。あなたは、ディレクトリツリーをナビゲート1、あなたがサムネイルを表示場所別:
  4. 起動し、具体的な例スクラッチ

からのタスクは、フォームは2つの部分を持って想像してみてください。ユーザーが別のディレクトリに移動すると、サムネイルを更新する必要があります。

最初に私はBackgroundWorkerAutoResetEventを使用してキャンセルを待つことを考えましたが、取り消しするとデッドロックしてしまったので、何かを混乱させる必要があります。次に、私はBGWとより初期のメカニズムを置き換えると思われるTPLについて読んでいます。

これはTPLを使用して簡単に行うことができますか?

答えて

18

注意すべきいくつかのこと:

  • あなたは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); 
    } 
} 
+0

それは一度だけ、トークンソースを作成し、StartNew' 'にするたびにそのトークンを渡しても大丈夫ですか? –

+0

それは子供の2本の缶のようなものだと思ってください(1缶からN缶:あなたは1つの終わりを持っていて、すべての開始タスクはゲットできます。 。 – JerKimball

+1

@dario_ramos私はあなたのコメントの質問がコメント(ここでは、http://stackoverflow.com/questions/14896248/deadlock-when-waiting-for-task-to-finish)で答えられたと信じていますが、完全性'キャンセル'の回答は 'CancellationTokenSource'をリセットしてキャンセルすることはできませんので、キャンセルをリクエストした場合は、キャンセルするにはもう一度キャンセルする必要があります。 – shambulator

関連する問題