Если у вас много логических задач, требующих постоянной обработки, и вы хотите, чтобы это выполнялось параллельно, используйте пул + планировщик.
Если вам нужно одновременно выполнять задачи, связанные с вводом-выводом, такие как загрузка материалов с удаленных серверов или доступ к диску, но нужно делать это, скажем, каждые несколько минут, тогда создайте свои собственные потоки и завершите их, когда закончите.
Изменить: по некоторым соображениям я использую пулы потоков для доступа к базе данных, физики / моделирования, AI (игр) и для задач со сценариями, выполняемых на виртуальных машинах, которые обрабатывают множество задач, определенных пользователем.
Обычно пул состоит из 2 потоков на процессор (в настоящее время, вероятно, 4), однако вы можете настроить необходимое количество потоков, если знаете, сколько вам нужно.
Изменить: причина создания собственных потоков связана с изменениями контекста (это когда потоки должны переключаться в процесс и выходить из него вместе с их памятью). Имея бесполезные изменения контекста, скажем, когда вы не используете свои потоки, просто оставив их, можно сказать, легко может вдвое снизить производительность вашей программы (скажем, у вас есть 3 спящих и 2 активных потока). Таким образом, если эти загружающие потоки просто ждут, они съедают массу ЦП и охлаждают кеш для вашего реального приложения.
Я бы посоветовал вам использовать пул потоков на C # по тем же причинам, что и на любом другом языке.
Если вы хотите ограничить количество запущенных потоков или не хотите накладных расходов на их создание и уничтожение, используйте пул потоков.
Под небольшими задачами книга, которую вы читаете, означает задачи с коротким сроком службы. Если для создания потока, который работает только в течение одной секунды, требуется десять секунд, это единственное место, где вы должны использовать пулы (не обращайте внимания на мои фактические цифры, это соотношение имеет значение).
В противном случае вы тратите большую часть своего времени на создание и уничтожение потоков, а не просто на выполнение работы, для которой они предназначены.
источник
Вот хороший обзор пула потоков в .Net: http://blogs.msdn.com/pedram/archive/2007/08/05/dedicated-thread-or-a-threadpool-thread.aspx
В сообщении также есть некоторые моменты, когда вам не следует использовать пул потоков и вместо этого запускать собственный поток.
источник
Я настоятельно рекомендую прочитать эту бесплатную электронную книгу: Threading in C # Джозефа Альбахари
По крайней мере, прочтите раздел «Начало работы». Электронная книга представляет собой отличное введение, а также содержит множество расширенной информации о многопоточности.
Знание, использовать ли пул потоков - это только начало. Далее вам нужно будет определить, какой метод входа в пул потоков лучше всего соответствует вашим потребностям:
Эта электронная книга объясняет все это и советует, когда их использовать, а когда создавать собственную ветку.
источник
Пул потоков предназначен для уменьшения количества переключений контекста между вашими потоками. Рассмотрим процесс, в котором запущено несколько компонентов. Каждый из этих компонентов может создавать рабочие потоки. Чем больше потоков в вашем процессе, тем больше времени тратится на переключение контекста.
Теперь, если бы каждый из этих компонентов ставил элементы в очередь в пул потоков, у вас было бы намного меньше накладных расходов на переключение контекста.
Пул потоков предназначен для максимизации работы, выполняемой вашими ЦП (или ядрами ЦП). Вот почему по умолчанию пул потоков раскручивает несколько потоков на процессор.
Есть некоторые ситуации, когда вы не хотите использовать пул потоков. Если вы ожидаете ввода-вывода или ожидаете события и т. Д., Вы связываете этот поток пула потоков, и он не может использоваться кем-либо еще. Та же идея применима к длительным задачам, хотя то, что составляет длительную задачу, субъективно.
Pax Diablo тоже хорошо замечает. Раскрутка потоков не бесплатна. Это требует времени, и они потребляют дополнительную память для своего стека. Пул потоков будет повторно использовать потоки для амортизации этой стоимости.
Примечание: вы спросили об использовании потока пула потоков для загрузки данных или выполнения дискового ввода-вывода. Вы не должны использовать для этого поток пула (по причинам, которые я указал выше). Вместо этого используйте асинхронный ввод-вывод (также известный как методы BeginXX и EndXX). Для
FileStream
этого было быBeginRead
иEndRead
. ДляHttpWebRequest
этого было быBeginGetResponse
иEndGetResponse
. Их сложнее использовать, но они являются правильным способом выполнения многопоточного ввода-вывода.источник
Остерегайтесь пула потоков .NET для операций, которые могут блокировать любую важную, переменную или неизвестную часть их обработки, поскольку он подвержен нехватке потоков. Рассмотрите возможность использования параллельных расширений .NET, которые предоставляют большое количество логических абстракций над многопоточными операциями. Они также включают новый планировщик, который должен стать улучшением ThreadPool. Смотрите здесь
источник
Одна из причин использовать пул потоков только для небольших задач заключается в том, что количество потоков пула ограничено. Если один из них используется в течение длительного времени, он останавливает использование этого потока другим кодом. Если это происходит много раз, то пул потоков может быть использован.
Использование пула потоков может иметь незначительные последствия - например, некоторые таймеры .NET используют потоки пула потоков и не срабатывают.
источник
Если у вас есть фоновая задача, которая будет существовать в течение длительного времени, например, в течение всего времени жизни вашего приложения, то создание собственного потока - разумная вещь. Если у вас короткие задания, которые необходимо выполнять в потоке, используйте пул потоков.
В приложении, в котором вы создаете много потоков, накладные расходы на создание потоков становятся существенными. Использование пула потоков создает потоки один раз и повторно использует их, что позволяет избежать накладных расходов на создание потоков.
В приложении, над которым я работал, переход от создания потоков к использованию пула потоков для короткоживущих потоков действительно помог сквозной передаче приложения.
источник
Для максимальной производительности при одновременном выполнении модулей напишите свой собственный пул потоков, в котором пул объектов потоков создается при запуске и переходит в режим блокировки (ранее приостановлен), ожидая запуска контекста (объект со стандартным интерфейсом, реализованный с помощью ваш код).
Так много статей о задачах, потоках и .NET ThreadPool не могут дать вам того, что вам нужно, чтобы принять решение о производительности. Но когда вы их сравниваете, выигрывают потоки и особенно пул потоков. Они лучше всего распределяются между процессорами и запускаются быстрее.
Следует обсудить тот факт, что основной исполнительной единицей Windows (включая Windows 10) является поток, и накладные расходы на переключение контекста ОС обычно незначительны. Проще говоря, мне не удалось найти убедительных доказательств многих из этих статей, независимо от того, утверждается ли в статье более высокая производительность за счет сохранения переключения контекста или лучшего использования ЦП.
Теперь немного реализма:
Большинству из нас не нужно, чтобы наше приложение было детерминированным, и у большинства из нас нет опыта работы с потоками, который, например, часто возникает при разработке операционной системы. То, что я написал выше, не для новичка.
Поэтому, возможно, наиболее важным является обсуждение того, что легко программировать.
Если вы создадите свой собственный пул потоков, вам придется немного написать, так как вам нужно будет заботиться об отслеживании статуса выполнения, как имитировать приостановку и возобновление и как отменить выполнение, в том числе в масштабе всего приложения. неисправность. Возможно, вам также придется позаботиться о том, хотите ли вы динамически наращивать свой пул, а также о том, какие ограничения емкости будет иметь ваш пул. Я могу написать такую структуру за час, но это потому, что я делал это много раз.
Возможно, самый простой способ написать исполнительную единицу - использовать Task. Прелесть Задачи в том, что вы можете создать ее и запустить ее прямо в коде (хотя может потребоваться осторожность). Вы можете передать токен отмены для обработки, когда хотите отменить задачу. Кроме того, он использует подход обещаний к цепочке событий, и вы можете заставить его возвращать определенный тип значения. Более того, с async и await существует больше возможностей, и ваш код будет более переносимым.
По сути, важно понимать плюсы и минусы задач, потоков и .NET ThreadPool. Если мне нужна высокая производительность, я буду использовать потоки и предпочитаю использовать свой собственный пул.
Легкий способ сравнения - запустить 512 потоков, 512 задач и 512 потоков ThreadPool. Вы обнаружите задержку в начале с потоками (отсюда и зачем писать пул потоков), но все 512 потоков будут запущены через несколько секунд, в то время как задачи и потоки .NET ThreadPool начнутся через несколько минут.
Ниже приведены результаты такого теста (четырехъядерный процессор i5 с 16 ГБ ОЗУ), дающий каждые 30 секунд на выполнение. Выполняемый код выполняет простой файловый ввод-вывод на SSD-диске.
Результаты теста
источник
Пулы потоков отлично подходят, когда у вас есть больше задач для обработки, чем доступных потоков.
Вы можете добавить все задачи в пул потоков и указать максимальное количество потоков, которые могут выполняться в определенное время.
Посетите эту страницу в MSDN: http://msdn.microsoft.com/en-us/library/3dasc8as(VS.80).aspx
источник
По возможности всегда используйте пул потоков, работайте на максимально возможном уровне абстракции. Пулы потоков скрывают для вас создание и удаление потоков, обычно это хорошо!
источник
В большинстве случаев вы можете использовать пул, поскольку избегаете дорогостоящего процесса создания потока.
Однако в некоторых сценариях вы можете создать поток. Например, если вы не единственный, кто использует пул потоков, а создаваемый поток является долгоживущим (чтобы избежать использования общих ресурсов) или, например, если вы хотите контролировать размер стека потока.
источник
Не забудьте исследовать фонового рабочего.
Я нахожу множество ситуаций, это дает мне то, что я хочу, без тяжелой работы.
Приветствия.
источник
Я обычно использую Threadpool всякий раз, когда мне нужно что-то сделать в другом потоке, и мне все равно, когда он запускается или заканчивается. Что-то вроде ведения журнала или, возможно, даже загрузки файла в фоновом режиме (хотя есть более эффективные способы сделать это в асинхронном стиле). Я использую свой собственный поток, когда мне нужно больше контроля. Кроме того, я обнаружил, что использование очереди Threadsafe (взломайте свою) для хранения «объектов команд» - это хорошо, когда у меня есть несколько команд, над которыми мне нужно работать в> 1 потоке. Таким образом, вы можете разделить файл Xml и поместить каждый элемент в очередь, а затем иметь несколько потоков, выполняющих некоторую обработку этих элементов. Я написал такую очередь еще в uni (VB.net!), Которую преобразовал на C #. Я включил его ниже без особой причины (этот код может содержать некоторые ошибки).
источник
Я хотел, чтобы пул потоков распределял работу по ядрам с минимально возможной задержкой, и это не должно было хорошо работать с другими приложениями. Я обнаружил, что производительность пула потоков .NET не так хороша, как могла бы быть. Я знал, что мне нужен один поток на ядро, поэтому я написал свой собственный класс замены пула потоков. Код предоставляется как ответ на другой вопрос StackOverflow здесь .
Что касается исходного вопроса, пул потоков полезен для разделения повторяющихся вычислений на части, которые могут выполняться параллельно (при условии, что они могут выполняться параллельно без изменения результата). Ручное управление потоками полезно для таких задач, как пользовательский интерфейс и ввод-вывод.
источник