ThreadPool.QueueUserWorkItem против Task.Factory.StartNew

79

в чем разница между приведенными ниже

ThreadPool.QueueUserWorkItem

против

Task.Factory.StartNew

Если приведенный выше код вызывается 500 раз для какой-то длительной задачи, означает ли это, что все потоки пула потоков будут задействованы?

Или TPL (2-й вариант) будет достаточно умен, чтобы просто обрабатывать потоки, меньшее или равное количеству процессоров?

stackoverflowuser
источник

Ответы:

93

Если вы собираетесь запустить длительную задачу с помощью TPL, вы должны указать TaskCreationOptions.LongRunning, что будет означать, что она не планирует ее в пуле потоков. (EDIT: Как было отмечено в комментариях, это является решение планировщика конкретным, а не жесткий и быстрый гарантии, но я надеюсь , что любой здравомыслящий производство планировщик позволит избежать планирования долго выполняющихся задач в пуле потоков.)

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

Назначение пула потоков - избежать того, чтобы короткие задачи сильно пострадали от создания нового потока по сравнению со временем, в течение которого они фактически выполняются. Если задача будет выполняться в течение длительного времени, влияние создания нового потока в любом случае будет относительно небольшим - и вы не хотите, чтобы потоки пула потоков потенциально заканчивались. (Это менее вероятно, но я сделал испытать его на более ранних версиях .NET.)

Лично, если бы у меня была возможность, я бы определенно использовал TPL на том основании, что TaskAPI довольно хорош, но не забудьте сказать TPL, что вы ожидаете, что задача будет выполняться в течение длительного времени.

EDIT: как отмечено в комментариях, см. Также сообщение в блоге команды PFX о выборе между TPL и пулом потоков :

В заключение я повторю то, что уже сказал разработчик ThreadPool из команды CLR:

Task is now the preferred way to queue work to the thread pool.

РЕДАКТИРОВАТЬ: Также из комментариев не забывайте, что TPL позволяет использовать настраиваемые планировщики , если вы действительно хотите ...

Джон Скит
источник
4
Я опасаюсь жесткого правила, TaskCreationOptions.LongRunningкоторое всегда избегает пула потоков. Похоже, это скорее директива, чем гарантия реализации. Я не в курсе?
Marc
1
@Marc: Ну, это зависит от планировщика - но это было бы довольно сумасшедшим планировщиком, чтобы планировать явно длительные задачи в пуле потоков, IMO.
Джон Скит
Просто чтобы добавить немного дополнительной информации - blogs.msdn.com/b/pfxteam/archive/2009/10/06/9903475.aspx
Брэд Семрад,
@Brad: Спасибо, добавлю ссылку на свой ответ.
Джон Скит,
1
Я бы также добавил, что TPL позволяет вам указывать собственный планировщик, включая настраиваемые планировщики, которые позволяют вам контролировать собственный параллелизм: msdn.microsoft.com/en-us/library/ee789351.aspx
Крис Шейн,