Преимущество использования Thread.Start по сравнению с QueueUserWorkItem - PullRequest
26 голосов
/ 26 марта 2009

В многопоточном программировании .NET, каковы критерии принятия решения об использовании ThreadPool.QueueUserWorkItem по сравнению с запуском собственного потока через new Thread () и Thread.Start ()?

В серверном приложении (скажем, приложении ASP.NET или службе WCF) я думаю, что ThreadPool всегда есть и доступен. А как насчет клиентского приложения, такого как приложение WinForms или WPF? Стоит ли раскручивать пул потоков? Если я просто хочу, чтобы 3 или 4 потока работали в течение короткого периода времени на некоторых вычислениях, лучше использовать QUWI или Thread.Start ().

Ответы [ 9 ]

21 голосов
/ 26 марта 2009

ThreadPool всегда там, однако, существует конечное число потоков, выделенных пулу в зависимости от количества процессоров. Для приложений ASP.NET, как правило, плохая идея использовать потоки, если вы действительно не запускаете асинхронный процесс и не знаете, что не будет большого количества запросов (помните, что в ThreadPool имеется конечное число потоков). которым вы делитесь со всем, что работает в вашем AppDomain, и существует реальное ограничение на общее количество потоков, которые вы хотите создать, используя new Thread () также.

Для приложений WinForms рассмотрите возможность использования BackgroundWorker вместо использования Thread или ThreadPool. Он использует ThreadPool, однако упрощает взаимодействие между потоками в многопоточном опытном программисте.

Обновлено

Избегайте использования ThreadPool.QueueUserWorkItem , поскольку пул приложений может исчезнуть в любое время. Переместите эту работу за пределы или используйте WebBackgrounder, если необходимо.

С Hanselman.com - «Контрольный список: что НЕ нужно делать в ASP.NET»

14 голосов
/ 26 марта 2009

Я собирался сделать этот комментарий, но он слишком длинный.
CodemonkeyKing, похоже, затронул важный момент, хотя, на мой взгляд, недостаточно сильно.

Существует множество критериев, которые вы можете использовать для описания кода. Будет ли оно использоваться в долгосрочном приложении или нет? Winforms приложение или нет? Это серверное или клиентское приложение? библиотека или автономный exe? и т. д.

Мне кажется, что если ваш код будет выполняться в автономном приложении и вы сможете контролировать весь окружающий код, то вы сможете свернуть свой собственный пул потоков, запустить собственные потоки, а также измерить и управлять затратами на запуск потоков, задержка потока и потребление ресурсов. Или вы можете использовать QUWI, но в любом случае это не убьет ваше приложение. Вы можете выбирать.

С другой стороны, если ваш код упакован в виде библиотеки, которую можно использовать на сервере - в ASP.NET, или, возможно, в приложении SQL CLR, или в службе WCF - тогда создавать действительно плохую идею потоки. Вам необходимо использовать QUWI или какой-либо другой механизм, который использует встроенный пул потоков (например, BackgroundWorker). Если он будет использоваться в клиентских приложениях с другими библиотеками, еще раз, QUWI требуется. Представьте, что каждая библиотека, желающая воспользоваться преимуществами многоядерных компьютеров, создала свои собственные потоки. Был бы полный хаос в приложениях, которые использовали больше, чем несколько библиотек. Безудержные темы, все конкурирующие за одни и те же ресурсы. Нет центральной координации между процессорами #threads и #.

Good hygeine требует , чтобы библиотека, независимо от того, будет ли она использоваться в клиентских или серверных приложениях, использовала общий пул потоков, что означает QUWI.

Последнее, что нужно осознать, это;

Управляемый поток - это фоновый поток или поток переднего плана. Фоновые потоки идентичны приоритетным потокам с одним исключением: фоновый поток не поддерживает работу управляемой среды выполнения. Как только все потоки переднего плана были остановлены в управляемом процессе (где файл .exe является управляемой сборкой), система останавливает все фоновые потоки и завершает работу.

Потоки, принадлежащие к пулу управляемых потоков (то есть потоки, свойство IsThreadPoolThread которых имеет значение true), являются фоновыми потоками. Все потоки, которые входят в среду управляемого выполнения из неуправляемого кода, помечаются как фоновые потоки. Все потоки, созданные при создании и запуске нового объекта Thread, по умолчанию являются приоритетными.

Если вы используете поток для мониторинга действия, такого как соединение через сокет, установите для его свойства IsBackground значение true, чтобы поток не препятствовал завершению вашего процесса.

с сайта MSDN .

4 голосов
/ 26 марта 2009

Эта дискуссия заинтересует вас
Когда я не должен использовать ThreadPool в .Net?

2 голосов
/ 25 мая 2010

Вот еще одно преимущество использования ThreadPool.QueueUserWorkItem.

У меня есть приложение winforms, у которого есть сердцебиение. Я изначально реализовал это с помощью

            heartbeat = new Thread(HeartbeatDoWork);
        heartbeat.Start();

Который отлично работает в 98% случаев. Однако, когда приложение закрывается, иногда оно не «умирает» должным образом, то есть процесс все еще виден в диспетчере задач.

Короче говоря, сердцебиение опубликовало событие, и оно обрабатывало событие (CAB pub / sub), где оно "застревало".

Исправить было легко, просто перейдите на использование

            ThreadPool.QueueUserWorkItem(HeartbeatDoWork);

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

2 голосов
/ 26 марта 2009

Если ваши задачи короткие, вы, скорее всего, увидите гораздо лучшую производительность, планируя задачи в пуле потоков через QueueUserWorkItem или BeginInvoke, поскольку вы избегаете повторяющихся затрат на создание и удаление собственных потоков.

Пул потоков, очевидно, также платит за создание потоков, но он повторно использует потоки, поэтому вы не платите стоимость за задачу.

Вы также можете взглянуть на Threading в C # (бесплатная электронная книга).

1 голос
/ 26 марта 2009

Пул потоков всегда доступен в приложениях .NET, независимо от его типа.

Стоимость запуска потока из пула потоков через ThreadPool.QueueUserWorkItem будет не больше стоимости запуска собственного потока и может быть меньше.

Если вам просто нужно несколько потоков на короткий период, используйте пул потоков. Вот для чего это.

0 голосов
/ 10 мая 2012

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

0 голосов
/ 20 августа 2010

Одним из преимуществ использования Thread.Start() является то, что вы можете намеренно прервать поток позже. В ThreadPool вы не можете контролировать выполнение потока после того, как поставили его в очередь.

0 голосов
/ 26 марта 2009

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

Но это в основном то, что очередь потоков уже делает для вас, так что вы можете также использовать ее. Это решенная проблема.

Подобные дебаты происходили в сообществе C ++ по поводу строк, верите или нет. Должны ли мы каждый написать свой собственный строковый класс или мы должны использовать std::string? Ответ зависит от того, хотите ли вы научиться писать строковый класс, или вы закончили с этим и хотите продолжить изобретать что-то новое.

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