Лучшая практика создания LongRunning Task - PullRequest
22 голосов
/ 27 октября 2011

Это хороший дизайн для фонового потока, который должен быть запущен с использованием Task API в .Net 4?Мое единственное беспокойство, если мы хотим отменить эту задачу, как бы я это сделал?Я знаю, что могу просто установить ProgramEnding в true, но знаю, что в API задач есть CancellationToken.

Это просто пример кода, так что один поток будет добавляться вколлекция и другая нить будет удаляться из него.Задача настроена как 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;
}

ОБНОВЛЕНИЕ: Я обнаружил, что могу удалить логическое значение ProgramEnding и использовать DataInQueue.CompleteAddingкоторые доводят нить до конца.

1 Ответ

20 голосов
/ 27 октября 2011

Как вы уже упоминали, вы можете использовать CancellationToken.Сделайте это следующим образом:

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

И позже в своем коде вы можете отменить задачу с помощью:

cancellationTokenSource.Cancel();

В вашем долгосрочном задании вы можете спросить токен, если отмена былазапрошено:

if (cancellationTokenSource.Token.IsCancellationRequested)
...