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

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

Похоже, что лучшим вариантом является использование ThreadPool, в таком случае, почему это не единственный вариант?

Каков ваш опыт вокруг этого?

9 ответов

Решение

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

  1. взаимодействовать с запущенным методом (например, чтобы убить его)
  2. запустить код в потоке STA (это случилось со мной)
  3. сохранить поток после того, как мое приложение умерло (ThreadPool темы это фоновые темы)
  4. в случае, если мне нужно изменить приоритет потока. Мы не можем изменить приоритет потоков в ThreadPool, который по умолчанию является нормальным.

PS: Статья MSDN "Управляемый пул потоков" содержит раздел под заголовком "Когда не следует использовать потоки пула потоков", с очень похожим, но несколько более полным списком возможных причин не использования пула потоков.

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

В качестве альтернативы, посмотрите на новую Parallel Extensions Framework, в которой есть некоторые полезные вещи, которые могут удовлетворить ваши потребности без необходимости использовать ThreadPool,

@ Эрик, мне нужно согласиться с Дином. Нитки дорогие. Вы не можете предполагать, что ваша программа работает только одна. Когда все жадны до ресурсов, проблема умножается.

Я предпочитаю создавать свои темы вручную и контролировать их самостоятельно. Это делает код очень простым для понимания.

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

Thread t = new Thread(new ThreadStart(DoSomething));  
t.Start();  
t.Join();  

Я надеюсь, что у вас обычно будет дополнительный код между Start() а также Join(), В противном случае, дополнительный поток бесполезен, и вы тратите ресурсы без причины.

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

Миллисекунда - это долгое время на современном оборудовании. Это 3 миллиона циклов на машине с частотой 3 ГГц. И опять же, вы не единственный, кто создает темы. Ваши потоки конкурируют за процессор наряду с потоками любой другой программы. Если вы используете не слишком много потоков, как и другая программа, то вместе вы использовали слишком много потоков.

Серьезно, не делайте жизнь более сложной, чем она должна быть. Не используйте пул потоков, если вам не нужно что-то очень конкретное, что он предлагает.

В самом деле. Не делай жизнь более сложной. Если вашей программе требуется несколько рабочих потоков, не изобретайте колесо заново. Используйте пул потоков. Вот почему это там. Будете ли вы катить свой собственный класс строки?

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

Два предостережения, конечно:

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

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

Пулы потоков не имеют смысла, когда вам нужны потоки, которые выполняют совершенно разные и несвязанные действия, которые нельзя считать "заданиями"; например, один поток для обработки событий GUI, другой для обработки бэкенда. Пулы потоков также не имеют смысла при обработке форм конвейера.

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

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

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

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

Потоки потоков подходят для задач, которые удовлетворяют обоим следующим критериям:

  1. Задаче не придется тратить сколько-нибудь значительного времени на ожидание чего-либо
  2. Все, что ожидает завершения задачи, вероятно, будет ожидать завершения многих задач, поэтому приоритет ее планирования не может сильно повлиять на ситуацию.

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

MSDN имеет список некоторых причин здесь:

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

Существует несколько сценариев, в которых целесообразно создавать собственные потоки и управлять ими вместо использования потоков потоков пула:

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

@Eric

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

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

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

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

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

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

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

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

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

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

Другие вопросы по тегам