Я несу ответственность за очистку после Задачи, созданной с флагом TaskCreationOptions.LongRunning? - PullRequest
7 голосов
/ 13 октября 2011

Когда вы создаете Task при указании TaskCreationOptions.LongRunning, новый поток создается специально для задачи. Если вы не укажете TaskCreationOptions.LongRunning, то используется пул потоков.

Пожалуйста, исправьте меня, если я ошибаюсь, но если используется пул потоков, вам не нужно dispose() задание (если вы не использовали объекты синхронизации внутри задачи, например Wait() в дочерней задаче ).

Если это так, я несу ответственность за очистку дополнительного потока, созданного с помощью флага TaskCreationOptions.LongRunning?

Если это так, то приемлемым является следующий шаблон:

var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning);

task.ContinueWith(x => task.Dispose());

Обратите внимание, что ContinueWith не имеет TaskContinuationOptions.LongRunning, поэтому должен использовать пул потоков.

При этом, однако, я прочитал, что поток, который перемещает состояние задачи в Completed, Faulted или Cancelled, имеет большое изменение при запуске продолжения.

Если бы кто-то мог пролить свет на это, я был бы очень признателен.

Ответы [ 3 ]

6 голосов
/ 13 октября 2011

Определенно не звоните Dispose() в продолжении - когда вы собираетесь утилизировать задачу продолжения?

AFAIK, единственная причина, по которой Task является одноразовой, - очистить дескриптор ожидания, созданный, если вы ожидаете выполнения задачи. Если вы не дождетесь выполнения задачи, дескриптор ожидания никогда не будет создан. В любом случае финализатор в конце концов очистится.

Кроме того, , если , задача создаст новый поток, он очистится после себя.

5 голосов
/ 13 октября 2011

TaskContinuationOptions.LongRunning является подсказкой для фабрики / планировщика заданий, все не так исправлено, как вы ее изображаете.

Я ожидаю, что ContinueWith будет выполняться в том же (longRunning) потоке, который может или не может быть запущен в ThreadPool.

И, насколько я знаю, очистка Задач происходит автоматически, поэтому я не стал бы беспокоиться о Dispose () здесь.

2 голосов
/ 13 октября 2011

Я не уверен насчет удаления Tasks, созданного с помощью опции LongRunning, но есть несколько вещей, которые приходят на ум в связи с показанным вами шаблоном.

  1. Какпоказано, что начальная длительная Task не наблюдается, что означает, что если операция по какой-либо причине выдает Exception, то в конечном итоге она будет переброшена в финализатор, что приведет к сбою процесса.
  2. В документации для Task говорится, что вы не должны вызывать Dispose, если Task фактически не завершен.Так что действительно, поэтому вы должны проверить, что Task завершено в продолжении, если вы собираетесь вызвать dispose.
  3. На самом деле вы звоните Dispose на Task, возвращаемом ContinueWith notоригинальное, долгосрочное задание.

Таким образом, вы можете сделать что-то вроде:

var task = Task.Factory.StartNew(() => {...}, TaskCreationOptions.LongRunning)
               .ContinueWith(x => 
   if(x.IsFaulted)
   { 
      x.Exception.Handle(_ => true); //just an example, you'll want to handle properly
   }
   else if(x.IsCompleted)
   {
       //do something with the result, if necessary
       x.Dispose());
   }); 

В конечном счете, я думаю, что важнее наблюдать Task, чем Dispose ит.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...