web-dev-qa-db-ja.com

ベストプラクティスの長期実行タスクの作成

これは、.Net 4のタスクAPIを使用して実行する必要があるバックグラウンドスレッドに適した設計ですか?私の唯一の懸念は、そのタスクをキャンセルしたい場合はどうすればよいですか? ProgramEndingtrueに設定できることはわかっていますが、Task APIにCancellationTokenがあることはわかっています。

これはサンプルコードにすぎないため、1つのスレッドがコレクションに追加され、別のスレッドがコレクションから削除されます。タスクはLongRunningとしてセットアップされます。これは、プログラムの実行中に継続的に実行する必要があるためです。

private void RemoveFromBlockingCollection()
{
    while (!ProgramEnding)
    {
       foreach (var x in DataInQueue.GetConsumingEnumerable())
       {
          Console.WriteLine("Task={0}, obj={1}, Thread={2}"
                          , Task.CurrentId, x + " Removed"
                          , Thread.CurrentThread.ManagedThreadId);
       }
    }
}

private void button1_Click(object sender, EventArgs e)
{
   DataInQueue = new BlockingCollection<string>();
   var t9 = Task.Factory.StartNew(RemoveFromBlockingCollection
                                 , TaskCreationOptions.LongRunning);

   for (int i = 0; i < 100; i++)
   {
     DataInQueue.Add(i.ToString());
     Console.WriteLine("Task={0}, obj={1}, Thread={2}", 
                       Task.CurrentId, i + " Added", 
                       Thread.CurrentThread.ManagedThreadId);
     Thread.Sleep(100);
   }
   ProgramEnding = true;
}

PDATE: ProgramEndingブール値を削除して、スレッドを終了させるDataInQueue.CompleteAddingを使用できることがわかりました。

25
Jon

すでに述べたように、CancellationTokenを使用できます。このようにしてください:

var cancellationTokenSource = new CancellationTokenSource();
Task.Factory.StartNew(RemoveFromBlockingCollection
                      , TaskCreationOptions.LongRunning
                      , cancellationTokenSource.Token);  

そして、後でコードで、次のようにしてタスクをキャンセルできます:

cancellationTokenSource.Cancel();

長期実行タスクでは、キャンセルが要求された場合にトークンを要求できます。

if (cancellationTokenSource.Token.IsCancellationRequested)
22
Fischermaen