Я хочу запустить задачу в фоновом потоке. Не хочу ждать завершения задач.
В .net 3.5 я бы сделал это:
ThreadPool.QueueUserWorkItem(d => { DoSomething(); });
В .net 4 рекомендуется использовать TPL. Я видел рекомендуемый общий шаблон:
Task.Factory.StartNew(() => { DoSomething(); });
Однако StartNew()
метод возвращает Task
объект, который реализует IDisposable
. Похоже, что люди, рекомендующие этот шаблон, не замечают этого. В документации MSDN по этому Task.Dispose()
методу говорится:
«Всегда вызывайте Dispose перед тем, как отпустить последнюю ссылку на Задачу».
Вы не можете вызвать dispose для задачи, пока она не будет завершена, поэтому ожидание основного потока и вызов dispose в первую очередь нарушит точку выполнения в фоновом потоке. Также, похоже, нет никакого завершенного / завершенного события, которое можно было бы использовать для очистки.
На странице MSDN в классе Task это не комментируется, а книга «Pro C # 2010 ...» рекомендует тот же шаблон и не дает никаких комментариев по удалению задач.
Я знаю, что если я просто оставлю это, финализатор поймает его в конце, но вернется ли он и укусит меня, когда я выполняю много задач типа «огонь и забывай», и поток финализатора будет перегружен?
Итак, мои вопросы:
- Приемлемо ли не звонить
Dispose()
поTask
классу в этом случае? И если да, то почему и существуют ли риски / последствия? - Есть ли документация, в которой это обсуждается?
- Или есть подходящий способ избавиться от
Task
предмета, который я пропустил? - Или есть другой способ выполнить задачи «выстрелил и забыл» с TPL?