Thread.Start () и ThreadPool.QueueUserWorkItem () - PullRequest
41 голосов
/ 01 июня 2011

Библиотека базовых классов Microsoft .NET предоставляет несколько способов создания потока и его запуска. По сути, вызов очень похож на любой другой, предоставляющий такой же вид сервиса: создайте объект, представляющий поток выполнения (или более), назначьте ему делегат, представляющий поток выполнения для выполнения, и, в конце концов, в зависимости от сигнатуры делегата, объект в качестве параметра.

Ну, есть два подхода (по сути):

1) Использование класса System.Threading.Thread.

Thread curr = new Thread(myfunction); /* In a class, myfunction is a void taking an object */
curr.Start(new Object()); /* Or something else to be downcast */

2) Использование класса System.Threading.ThreadPool.

ThreadPool.QueueUserWorkItem(myfunction, new Object()); /* Same philosophy here */

Есть ли какие-либо особые причины, по которым я должен использовать 1) или 2)?

  • Причины производительности?
  • Шаблоны
  • Каков наилучший подход?

У меня такое ощущение, что ответ таков: "Зависит от ситуации". Не могли бы вы перечислить некоторые ситуации, когда один подход лучше другого?

Ответы [ 7 ]

46 голосов
/ 01 июня 2011

Запуск нового потока может быть очень дорогой операцией. Пул потоков повторно использует потоки и таким образом амортизирует стоимость. Если вам не нужен выделенный поток, рекомендуется использовать пул потоков. Используя выделенный поток, вы получаете больший контроль над атрибутами, специфичными для потока, такими как приоритет, культура и так далее. Кроме того, вы не должны выполнять долго выполняющиеся задачи в пуле потоков, так как это заставит пул создавать дополнительные потоки.

В дополнение к упомянутым вами опциям .NET 4 предлагает несколько отличных абстракций для параллелизма. Проверьте классы Task и Parallel, а также все новые методы PLINQ.

12 голосов
/ 01 июня 2011

Пул управляемых потоков содержит несколько очень хороших рекомендаций о том, когда НЕ следует использовать пул потоков.

По моему опыту, вы хотите создать свой собственный поток, когда вам нужен постоянный, выделенный, долго работающий поток. Для всего остального используйте асинхронные делегаты или что-то вроде QueueUserWorkItem, BackgroundWorker или функции, связанные с задачами .NET 4.0.

7 голосов
/ 11 декабря 2012

Темы в ThreadPool являются фоновыми потоками; Все потоки, созданные и запущенные новым объектом Thread, являются приоритетными.

Фоновый поток не поддерживает работу среды управляемого выполнения.

Подробнее см. http://msdn.microsoft.com/en-us/library/h339syd0.aspx.

6 голосов
/ 14 октября 2014

В .NET 4.5.2 добавлен новый метод: HostingEnvironment.QueueBackgroundWorkItem .

Похоже, это альтернатива ThreadPool.QueueUserWorkItem.Оба ведут себя одинаково, но есть несколько приятных преимуществ использования нового метода при работе в ASP.NET:

Метод HostingEnvironment.QueueBackgroundWorkItem позволяет планировать небольшие фоновые рабочие элементы.ASP.NET отслеживает эти элементы и не позволяет IIS внезапно завершать рабочий процесс до тех пор, пока все фоновые рабочие элементы не будут завершены.Этот метод нельзя вызывать вне домена управляемых приложений ASP.NET.

2 голосов
/ 01 июня 2011

Используя ThreadPool, вы меньше контролируете систему потоков.Это компромисс, чтобы упростить процесс для вас.Если у вас есть все, что вам нужно от ThreadPool, вы можете свободно использовать его.Если вам нужен больший контроль над потоками, вам, конечно, нужно использовать классы Thread.

1 голос
/ 01 июня 2011

ThreadPool.QueueUserWorkItem () в основном для сценариев запуска и забывания, когда приложение не зависит от того, завершатся операции или нет.

Использование классических потоков для детального управления.

0 голосов
/ 26 ноября 2018

Вы должны использовать ThreadPool.QueueUserWorkItem за исключением случаев, когда:

  • Вам нужна нить переднего плана.

  • Вам нужна нить, чтобы иметьопределенный приоритет.

  • У вас есть задачи, из-за которых поток блокируется на длительные периоды времени.Пул потоков имеет максимальное количество потоков, поэтому большое количество заблокированных потоков пула потоков может помешать запуску задач.

  • Вам необходимо разместить потоки в однопотоковой квартире.Все потоки ThreadPool находятся в многопоточной квартире.

  • Необходимо иметь стабильную идентификацию, связанную с потоком, или назначить поток задаче.

Ссылка ссылка .

...