Другие ответы здесь, похоже, не учитывают самый важный момент:
Если вы не пытаетесь распараллелить операцию, интенсивно использующую ЦП, чтобы ускорить ее выполнение на сайте с низкой нагрузкой, нет никакого смысла использовать рабочий поток вообще.
Это касается как бесплатных потоков, созданных new Thread(...), так и рабочих потоков ThreadPool, отвечающих на QueueUserWorkItemзапросы.
Да, это правда, вы можете заморозить ThreadPoolпроцесс ASP.NET, поставив в очередь слишком много рабочих элементов. Это предотвратит обработку дальнейших запросов ASP.NET. Информация в статье верна в этом отношении; тот же пул потоков используется для QueueUserWorkItemобслуживания запросов.
Но если вы действительно ставите в очередь достаточно рабочих элементов, чтобы вызвать голод, тогда вам следует истощить пул потоков! Если вы выполняете буквально сотни операций с интенсивным использованием ЦП одновременно, какой смысл иметь другой рабочий поток для обслуживания запроса ASP.NET, когда машина уже перегружена? Если вы столкнулись с такой ситуацией, вам нужно полностью переделать дизайн!
В большинстве случаев я вижу или слышу о том, что многопоточный код используется ненадлежащим образом в ASP.NET, это не для постановки в очередь работы, интенсивно использующей процессор. Это для постановки в очередь работы, связанной с вводом-выводом. И если вы хотите выполнять операции ввода-вывода, вам следует использовать поток ввода-вывода (порт завершения ввода-вывода).
В частности, вы должны использовать асинхронные обратные вызовы, поддерживаемые любым классом библиотеки, который вы используете. Эти методы всегда очень четко обозначены; они начинаются со слов Beginи End. Как и в Stream.BeginRead, Socket.BeginConnect, WebRequest.BeginGetResponse, и так далее.
Эти методы действительно используют ThreadPool, но они используют IOCP, которые не мешают запросам ASP.NET. Это особый вид облегченного потока, который может быть «разбужен» сигналом прерывания от системы ввода-вывода. А в приложении ASP.NET у вас обычно есть один поток ввода-вывода для каждого рабочего потока, поэтому для каждого отдельного запроса может быть поставлена в очередь одна асинхронная операция. Это буквально сотни асинхронных операций без значительного снижения производительности (при условии, что подсистема ввода-вывода может не отставать). Это намного больше, чем вам когда-либо понадобится.
Просто имейте в виду, что асинхронные делегаты не работают таким образом - они в конечном итоге будут использовать рабочий поток, как и ThreadPool.QueueUserWorkItem. На это способны только встроенные асинхронные методы классов библиотеки .NET Framework. Вы можете сделать это сами, но это сложно и немного опасно и, вероятно, выходит за рамки этого обсуждения.
На мой взгляд, лучший ответ на этот вопрос - не использовать ThreadPool или фоновый Threadэкземпляр в ASP.NET . Это совсем не похоже на запуск потока в приложении Windows Forms, где вы делаете это, чтобы пользовательский интерфейс оставался отзывчивым и не заботился о том, насколько он эффективен. В ASP.NET вас беспокоит пропускная способность , и все эти переключения контекста для всех этих рабочих потоков абсолютно убивают вашу пропускную способность, независимо от того, используете вы ThreadPoolили нет.
Пожалуйста, если вы обнаружите, что пишете код потоковой передачи в ASP.NET - подумайте, можно ли его переписать для использования уже существующих асинхронных методов, а если нет, то подумайте, действительно ли вам нужен код чтобы вообще работать в фоновом потоке. В большинстве случаев вы, вероятно, будете добавлять сложность без чистой выгоды.