Использование ThreadPool.QueueUserWorkItem в ASP.NET в сценарии с высоким трафиком

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

Итак, вот как я до сих пор выполнял небольшие асинхронные задачи:

ThreadPool.QueueUserWorkItem(s => PostLog(logEvent))

И статья предлагает вместо этого явно создать поток, аналогично следующему:

new Thread(() => PostLog(logEvent)){ IsBackground = true }.Start()

Преимущество первого метода состоит в том, что он управляем и ограничен, но есть вероятность (если статья верна), что фоновые задачи затем соперничают за потоки с обработчиками запросов ASP.NET. Второй метод освобождает ThreadPool, но за счет того, что он неограничен и, следовательно, потенциально использует слишком много ресурсов.

Итак, мой вопрос: правильный ли совет в статье?

Если ваш сайт получает так много трафика, что ваш ThreadPool заполняется, тогда лучше выйти за пределы диапазона, или полный ThreadPool будет означать, что вы в любом случае исчерпываете свои ресурсы, и в этом случае вы не следует пытаться начинать свои собственные темы?

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


person Michael Hart    schedule 25.08.2009    source источник
comment
Сюжет сгущается - я нашла эту статью (blogs.msdn.com/nicd/archive/2007/04/16/), который я не могу декодировать. С одной стороны, кажется, что IIS 6.0+ всегда обрабатывает запросы в рабочих потоках пула потоков (и что более ранние версии могли делать это), но есть следующее: Однако, если вы используете новый Асинхронные страницы .NET 2.0 (Async = true) или ThreadPool.QueueUserWorkItem (), тогда асинхронная часть обработки будет выполняться внутри [потока порта завершения]. Асинхронная часть обработки?   -  person Jeff Sternal    schedule 15.01.2010
comment
Еще одна вещь - это должно быть достаточно легко протестировать на установке IIS 6.0+ (которой у меня сейчас нет), проверив, являются ли доступные рабочие потоки пула потоков ниже, чем его максимальное количество рабочих потоков, а затем проделав то же самое в очереди. рабочие элементы.   -  person Jeff Sternal    schedule 15.01.2010


Ответы (11)


Другие ответы здесь, похоже, не учитывают самый важный момент:

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

Это касается как бесплатных потоков, созданных 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 - подумайте, можно ли его переписать для использования уже существующих асинхронных методов, а если нет, то подумайте, действительно ли вам нужен код для запуска в фоновом потоке вообще. В большинстве случаев вы, вероятно, будете добавлять сложность без чистой выгоды.

person Aaronaught    schedule 15.04.2010
comment
Спасибо за подробный ответ, и вы правы, я стараюсь по возможности использовать асинхронные методы (в сочетании с асинхронными контроллерами в ASP.NET MVC). В случае моего примера с удаленным регистратором это именно то, что я могу сделать. Однако это интересная проблема дизайна, потому что она подталкивает асинхронную обработку полностью вниз к самому низкому уровню вашего кода (то есть реализации регистратора), вместо того, чтобы иметь возможность решить ее, скажем, с уровня контроллера (в последнем случае , вам понадобятся, например, две реализации регистратора, чтобы иметь возможность выбирать). - person Michael Hart; 15.04.2010
comment
@Michael: асинхронные обратные вызовы обычно довольно легко обернуть, если вы хотите поднять их на большее количество уровней; вы можете создать фасад вокруг асинхронных методов и обернуть их, например, одним методом, который использует Action<T> в качестве обратного вызова. Если вы имеете в виду, что выбор между использованием рабочего потока или потока ввода-вывода происходит на самом низком уровне, это сделано намеренно; только этот уровень может решить, нужен ли ему IOCP. - person Aaronaught; 15.04.2010
comment
Хотя, что интересно, только .NET ThreadPool ограничивает вас таким образом, вероятно, потому, что они не доверяли разработчикам, чтобы они все сделали правильно. Неуправляемый пул потоков Windows имеет очень похожий API, но на самом деле позволяет вам выбирать тип потока. - person Aaronaught; 15.04.2010
comment
Акроним должен быть IOCP, а не IOPC, может ли кто-нибудь, набравший достаточно очков, исправить ответ - person John Simons; 05.01.2011
comment
Порты завершения ввода-вывода (IOCP). описание IOCP не совсем корректное. в IOCP у вас есть статическое количество рабочих потоков, которые по очереди работают над ВСЕМИ незавершенными задачами. не путать с пулами потоков, которые могут быть фиксированными или динамическими по размеру, НО имеют один поток на задачу - ужасно масштабируются. в отличие от ASYNC, у вас нет одного потока для каждой задачи. поток IOCP может немного поработать над задачей 1, затем переключиться на задачу 3, задачу 2, а затем снова вернуться к задаче 1. состояния сеанса задачи сохраняются и передаются между потоками. - person MickyD; 12.01.2012
comment
А как насчет вставок в базу данных? Есть ли команда ASYNC SQL (например, «Выполнить»)? Вставки в базу данных - это самая медленная операция ввода-вывода (из-за блокировки), а ожидание основного потока вставки строки (строк) - это просто пустая трата циклов ЦП. - person Ian Thompson; 29.05.2014
comment
@IanThompson: Я бы посоветовал вам прочтите документацию для любого используемого вами драйвера / библиотеки базы данных. На этот вопрос нет однозначного ответа, и со временем он может меняться. Oracle, например, только недавно начал поддерживать асинхронный режим и все еще может не поддерживать асинхронный режим в стиле TPL. - person Aaronaught; 31.05.2014
comment
@Aaronaught, спасибо. ODBCCommand не поддерживает его, но в SQLCommand есть ASYNC BeginExecuteNonQuery, который я успешно использовал. - person Ian Thompson; 31.05.2014

Согласно Томасу Маркуадту из группы ASP.NET в Microsoft, безопасно использовать ASP.NET ThreadPool (QueueUserWorkItem).

Из статьи:

В) Если мое приложение ASP.NET использует потоки CLR ThreadPool, не буду ли я голодать по ASP.NET, которая также использует CLR ThreadPool для выполнения запросов? ..

A) Подводя итог, не беспокойтесь о том, что ASP.NET не хватает потоков, и если вы считаете, что здесь есть проблема, дайте мне знать, и мы позаботимся об этом.

В) Должен ли я создавать свои собственные потоки (новый поток)? Разве это не будет лучше для ASP.NET, поскольку он использует CLR ThreadPool.

А) Пожалуйста, не надо. Или, иначе говоря, нет !!! Если вы действительно умны - намного умнее меня - тогда вы можете создавать свои собственные темы; в противном случае даже не думай об этом. Вот несколько причин, по которым вам не следует часто создавать новые темы:

  1. Это очень дорого по сравнению с QueueUserWorkItem ... Кстати, если вы можете написать пул потоков лучше, чем CLR, я рекомендую вам подать заявку на работу в Microsoft, потому что мы определенно ищем таких людей, как вы !.
person Tim P.    schedule 17.05.2011

Веб-сайты не должны порождать темы.

Обычно вы переносите эту функцию в службу Windows, с которой затем общаетесь (я использую MSMQ, чтобы общаться с ними).

-- Редактировать

Я описал здесь реализацию: Фоновая обработка на основе очередей в Веб-приложение ASP.NET MVC

-- Редактировать

Чтобы объяснить, почему это даже лучше, чем просто потоки:

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

Это также позволяет вам выполнять пакетную обработку любой задачи, которую вы пытаетесь выполнить (отправлять электронные письма / что-то еще).

person Noon Silk    schedule 25.08.2009
comment
Я бы не согласился, что это общее заявление всегда верно - особенно для некритических задач. Создание службы Windows только для целей асинхронного ведения журнала определенно кажется излишним. Кроме того, этот вариант не всегда доступен (возможность развернуть MSMQ и / или службу Windows). - person Michael Hart; 25.08.2009
comment
Конечно, но это «стандартный» способ реализации асинхронных задач с веб-сайта (тема очереди по сравнению с каким-то другим процессом). - person Noon Silk; 25.08.2009
comment
Не все асинхронные задачи одинаковы, поэтому, например, в ASP.NET существуют асинхронные страницы. Если я хочу получить результат от удаленной веб-службы для отображения, я не буду делать это через MSMQ. В этом случае я пишу в журнал с помощью удаленного поста. Написание службы Windows или подключение MSMQ для этого не подходит (и я тоже не могу, поскольку это конкретное приложение находится в Azure). - person Michael Hart; 25.08.2009
comment
Подумайте: вы пишете на удаленный хост? Что делать, если этот хост не работает или недоступен? Вы хотите еще раз попробовать написать? Может быть, ты будешь, а может, и нет. С вашей реализацией трудно повторить попытку. С сервисом это становится довольно тривиальным. Я понимаю, что вы, возможно, не сможете это сделать, и я позволю кому-нибудь другому ответить на конкретные проблемы с созданием потоков с веб-сайтов [т.е. если ваш поток не был фоном и т. д.], но я обрисовываю «правильный» способ сделать это. Я не знаком с azure, хотя использовал ec2 (вы можете установить на нем ОС, так что все в порядке). - person Noon Silk; 25.08.2009
comment
@silky, спасибо за комментарии. Я сказал некритично, чтобы избежать этого более тяжелого (но надежного) решения. Я прояснил вопрос, чтобы было ясно, что я не прошу рекомендаций по работе с элементами в очереди. Azure поддерживает этот тип сценария (у него есть собственное хранилище очередей), но операция постановки в очередь слишком дорога для синхронного ведения журнала, поэтому мне в любом случае понадобится асинхронное решение. В моем случае я знаю о подводных камнях сбоя, но я не собираюсь добавлять дополнительную инфраструктуру на случай, если этот конкретный поставщик журналов выйдет из строя - у меня есть и другие поставщики журналов. - person Michael Hart; 25.08.2009
comment
Не беспокойтесь, извиняюсь, если я прозвучал слишком грубо :) - person Noon Silk; 25.08.2009

Я определенно думаю, что общей практикой для быстрой асинхронной работы с низким приоритетом в ASP.NET было бы использование пула потоков .NET, особенно для сценариев с высоким трафиком, поскольку вы хотите, чтобы ваши ресурсы были ограничены.

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

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

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

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

person Sam    schedule 25.08.2009

Вам следует использовать QueueUserWorkItem и избегать создания новых потоков, как если бы вы избежали чумы. Для наглядного изображения, объясняющего, почему вы не будете морить ASP.NET голодом, поскольку он использует тот же ThreadPool, представьте себе очень опытного жонглера, который двумя руками держит в полете полдюжины кеглей для боулинга, мечей или чего-то еще. Чтобы наглядно понять, почему создание собственных потоков - это плохо, представьте, что происходит в Сиэтле в час пик, когда интенсивно используемые въездные пандусы на шоссе позволяют транспортным средствам немедленно выезжать на поток, а не использовать свет и ограничивать количество въездов до одного каждые несколько секунд. . Наконец, подробное объяснение можно найти по этой ссылке:

http://blogs.msdn.com/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx

Спасибо, Томас

person Thomas    schedule 15.04.2010
comment
Эта ссылка очень полезна, спасибо за это, Томас. Мне было бы интересно услышать, что вы думаете об ответе @Aaronaught. - person Michael Hart; 15.04.2010
comment
Я согласен с Aaronaught и сказал то же самое в своем сообщении в блоге. Я сказал так: в попытке упростить это решение вам следует переключаться [на другой поток] только в том случае, если вы иначе заблокировали бы поток запроса ASP.NET, пока вы ничего не делаете. Это чрезмерное упрощение, но я пытаюсь сделать решение простым. Другими словами, не делайте этого для неблокирующей вычислительной работы, но делайте это, если вы делаете запросы асинхронной веб-службы к удаленному серверу. Слушайте Aaronaught! :) - person Thomas; 15.04.2010

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

Использование ThreadPool в ASP.NET не будет мешать рабочим потокам ASP.NET. Использование ThreadPool - это нормально.

Также было бы приемлемо настроить один поток, который предназначен только для регистрации сообщений и использования шаблона производитель / потребитель для передачи сообщений журнала в этот поток. В этом случае, поскольку поток является долгоживущим, вы должны создать один новый поток для запуска регистрации.

Использование новой цепочки для каждого сообщения определенно излишне.

Другой альтернативой, если вы говорите только о ведении журнала, является использование библиотеки вроде log4net. Он обрабатывает ведение журнала в отдельном потоке и заботится обо всех проблемах контекста, которые могут возникнуть в этом сценарии.

person Samuel Neff    schedule 14.10.2009
comment
@Sam, я на самом деле использую log4net и не вижу, чтобы журналы записывались в отдельном потоке - есть ли какая-то опция, которую мне нужно включить? - person Michael Hart; 15.10.2009

Я бы сказал, что статья неправильная. Если у вас большой магазин .NET, вы можете безопасно использовать этот пул в нескольких приложениях и на нескольких веб-сайтах (используя отдельные пулы приложений), просто на основе одного оператора в Документация по ThreadPool:

На каждый процесс приходится один пул потоков. Пул потоков по умолчанию имеет размер 250 рабочих потоков на доступный процессор и 1000 потоков завершения ввода-вывода. Количество потоков в пуле потоков можно изменить с помощью метода SetMaxThreads. Каждый поток использует размер стека по умолчанию и работает с приоритетом по умолчанию.

person Christopher Nobles    schedule 14.10.2009
comment
Одно приложение, работающее в одном процессе, полностью способно выйти из строя! (Или, по крайней мере, ухудшение собственной производительности настолько, чтобы сделать пул потоков проигрышным.) - person Jeff Sternal; 15.10.2009
comment
Итак, я предполагаю, что запросы ASP.NET используют потоки завершения ввода-вывода (в отличие от рабочих потоков) - это правильно? - person Michael Hart; 15.10.2009
comment
Из статьи Фрица Ониона я дал ссылку в своем ответе: Эта парадигма меняет [с IIS 5.0 на IIS 6.0] способ обработки запросов в ASP.NET. Вместо отправки запросов от inetinfo.exe к рабочему процессу ASP.NET, http.sys напрямую ставит в очередь каждый запрос в соответствующем процессе. Таким образом, все запросы теперь обслуживаются рабочими потоками, взятыми из пула потоков CLR, а не потоками ввода-вывода. (мой акцент) - person Jeff Sternal; 15.10.2009
comment
Хммм, я все еще не совсем уверен ... Эта статья написана в июне 2003 года. Если вы читаете эту статью из мая 2004 года (правда, еще довольно старую), там говорится, что тестовая страница Sleep.aspx может использоваться для хранения ASP. Поток ввода-вывода .NET занят, где Sleep.aspx просто переводит текущий выполняющийся поток в спящий режим: msdn.microsoft.com/en-us/library/ms979194.aspx - Когда у меня будет возможность, я посмотрю, смогу ли я кодировать этот пример и протестировать его на IIS 7 и .NET 3.5. - person Michael Hart; 15.10.2009
comment
Да, текст этого абзаца сбивает с толку. Далее в этом разделе ссылка на тему поддержки (поддержка. microsoft.com/default.aspx?scid=kb;EN-US;816829), который проясняет ситуацию: выполнение запросов в потоках завершения ввода-вывода было проблемой .NET Framework 1.0, которая была исправлена ​​в ASP.NET 1.1. Накопительный пакет исправлений от июня 2003 г. (после которого ВСЕ запросы теперь выполняются в рабочих потоках). Что еще более важно, этот пример ясно показывает, что пул потоков ASP.NET - это тот же пул потоков, который предоставлен System.Threading.ThreadPool. - person Jeff Sternal; 15.10.2009

На прошлой неделе мне задали аналогичный вопрос на работе, и я дам вам такой же ответ. Почему вы выполняете многопоточные веб-приложения по запросу? Веб-сервер - это фантастическая система, сильно оптимизированная для своевременного предоставления множества запросов (т.е. многопоточность). Подумайте, что происходит, когда вы запрашиваете практически любую страницу в Интернете.

  1. Сделан запрос на какую-то страницу
  2. HTML возвращается
  3. Html сообщает клиенту, что нужно делать дополнительные запросы (js, css, изображения и т. Д.)
  4. Дополнительная информация высылается обратно

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

Сэм также прав в том, что использование пула потоков в CLR не вызовет проблем с пулом потоков в IIS. Однако здесь следует обратить внимание на то, что вы не создаете потоки из процесса, вы создаете новые потоки из потоков пула потоков IIS. Есть разница, и различие важно.

Потоки против процесса

И потоки, и процессы - это методы распараллеливания приложения. Однако процессы являются независимыми исполнительными модулями, которые содержат свою собственную информацию о состоянии, используют свои собственные адресные пространства и взаимодействуют друг с другом только через механизмы межпроцессного взаимодействия (обычно управляемые операционной системой). Приложения обычно делятся на процессы на этапе проектирования, и главный процесс явно порождает подпроцессы, когда имеет смысл логически разделить важные функции приложения. Другими словами, процессы - это архитектурная конструкция.

Напротив, поток - это конструкция кодирования, которая не влияет на архитектуру приложения. Один процесс может содержать несколько потоков; все потоки в процессе имеют одно и то же состояние и одно и то же пространство памяти и могут напрямую взаимодействовать друг с другом, потому что они используют одни и те же переменные.

Источник

person Ty.    schedule 15.10.2009
comment
@Ty, спасибо за ввод, но я хорошо знаю, как работает веб-сервер, и это не имеет отношения к вопросу - опять же, как я сказал в вопросе, я не прошу совета по этому поводу как архитектурный проблема. Я прошу конкретную техническую информацию. Что касается регистратора, который уже должен иметь асинхронный процесс - как вы думаете, этот асинхронный процесс должен быть записан реализацией регистратора? - person Michael Hart; 16.10.2009

Вы можете использовать Parallel.For или Parallel.ForEach и определить предел возможных потоков, которые вы хотите выделить для бесперебойной работы и предотвращения истощения пула.

Однако при работе в фоновом режиме вам нужно будет использовать чистый стиль TPL, указанный ниже, в веб-приложении ASP.Net.

var ts = new CancellationTokenSource();
CancellationToken ct = ts.Token;

ParallelOptions po = new ParallelOptions();
            po.CancellationToken = ts.Token;
            po.MaxDegreeOfParallelism = 6; //limit here

 Task.Factory.StartNew(()=>
                {                        
                  Parallel.ForEach(collectionList, po, (collectionItem) =>
                  {
                     //Code Here PostLog(logEvent);
                  }
                });
person khayam    schedule 31.03.2019

Я не согласен с указанной статьей (C # feeds.com). Создать новую ветку легко, но опасно. Оптимальное количество активных потоков для запуска на одном ядре на самом деле удивительно мало - менее 10. Слишком легко заставить машину тратить время на переключение потоков, если потоки создаются для второстепенных задач. Потоки - это ресурс, ТРЕБУЮЩИЙ управления. Абстракция WorkItem предназначена для этого.

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

Наконец, в статье делается несколько довольно общих заявлений об опасностях использования ThreadPool, но для их поддержки действительно требуется что-то конкретное.

person Timbo    schedule 03.02.2010

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

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

person bmm6o    schedule 05.03.2010