Как работает Thread Pool?

    clip_image001

    Пул потоков

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

    Как же работает Thread Pool в .NET 4 и выше, читаем дальше тут
    Поделиться публикацией
    Реклама помогает поддерживать и развивать наши сервисы

    Подробнее
    Реклама
    Комментарии 18
    • –5
      > переключение между потоками – это дорогостоящая операция
      Насколько я знаю, в .NET потоки не имеют ничего общего с потоками Windows, и переключаются мгновенно.
      • +2
        При использовании ThreadPool.QueueUserWorkItem — да. .NET потоки это такие же простые «потоки» Windows только ними управляет CLR, по этому у них много общего
        • 0
          это тоже неправда. потоки которые крутятся в ThreadPool — обычные OS threads. CLR ими довольно в меру управляет. он следит кому потоку какую задачу отдать, но CLR не занимается диспетчеризацией потоков, потому что этим занимается OS.
          • +1
            А я что написал? конечно, это обыные потоки, про диспетчеризацию ни слова в комменте
            • 0
              «только ними управляет CLR» звучало как некоторая антитеза тому что ими управляет Windows. может я не так прочитал просто.

              — ".NET потоки не имеют ничего общего с потоками Windows"
              — «При использовании ThreadPool.QueueUserWorkItem — да»

              с этим я тоже не согласился. просто уровень абстракции немного приподнят, а потоки-то те же.
              • +2
                Вы просто не так прочитали.

                «При использовании ThreadPool.QueueUserWorkItem — да»

                Это ответ на «Насколько я знаю, в .NET потоки переключаются мгновенно»

                Возможно я не точно сформулировал ответ.
        • +1
          это неправда. была такая задумка, но на деле .net потоки отображаются на OS потоки 1:1. Со всеми вытекающими.
        • +2
          ThreadPool — достаточно опасная штука и его лучше не использовать, так как можно легко израсходовать все потоки пула.
          • +2
            опасность скорее заключается в том, что ThreadPool общий ресурс и можно неаккуратным использованием подорвать работу разных системных вещей .net. Например все асинхронные вызовы делегатов крутятся в ThreadPool и WCF там живет.
            • 0
              Я это и имел ввиду, опасность не в том, что израсходуем потоки, а в последствиях.

              Кстати, еще я натыкался на разное поведение ThreadPool в .net и mono, например, следующий код работает в .net, но из-за чего-то висит в mono — пришлось переписать на явный Thread:

              class Program
              {
                  static HttpWebRequest request;
                  static WebResponse responce;
                  static void Callback(IAsyncResult future)
                  {
                      responce = request.EndGetResponse(future);
                      ThreadPool.QueueUserWorkItem(_ => Process());
                  }
                  static void Process() 
                  {
                      var stream = responce.GetResponseStream();
                      var html = new StreamReader(stream).ReadToEnd();
                      Console.WriteLine(html.Length);
                      ((IDisposable)responce).Dispose();
                  }
                  static void Main(string[] args)
                  {
                      ThreadPool.QueueUserWorkItem(delegate
                      {
                          request = HttpWebRequest.Create("http://google.com") as HttpWebRequest;
                          request.BeginGetResponse(Callback, null);
                      });
                      Console.ReadLine();
                  }
              }
            • +1
              Ага. Баги при его исчерпании получаются очень интересные. Вот хорошая замена встроенному пулу: smartthreadpool.codeplex.com/
              • +1
                Что значит «исчерпение» в вашем понимании?
                • 0
                  pool exhaust, общепринятый термин. Это когда в пуле кончились свободные элементы (в случае thread pool — потоки). Возможно, по-русски это называется правильно не так, я не знаю.
                  • +1
                    За ссылку на проект спасибо. Но я не вижу возможности использовать такой проект в продакшене. Потому что многопоточность штука специфическая и у меня сомнения что smartpool так же хорошо отлажен как и встроеный пул. Тем более после выхода TPL.

                    Новый TPL мне кажется должен решать эти проблемы, так как запускать(или queue новую задачу для worker thread) или не запускать поток решает именно он, а QueueUserWorkItem всегда однозначно queue новую задачу для worker thread.

                    Да, ситуация с «исчерпанием» возможна. Но лимиты по умолчанию достаточно велики — это 250 рабочих потоков на CPU и 1000 I/O потоков на процесс. Мало того эти лимиты можно изменить — увеличить либо уменшить используя ThreadPool.SetMaxThreads.

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

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

                    И теперь давайте рассмотрим ситуацию. У сервера есть 1000 клиентов и на каждого из них при его запросе будет открыватся асинхронная операция — либо паралельные вычисления либо I/O. И мы очень легко получим это «исчерпение». Но для такого сервера нужно лимитировать число одновременных клиентов для которых запускаются асинхронные операции. Т.е. для 1000 клиентов к примеру открываем, остальные будут ждать.

                    Если не делать такого лимитирования то при определенной нагрузке на сервер, при определенном числе пользователей, каким бы ни был пул потоков мы придем к этому «исчерпение».
                    • 0
                      Отлажен он хорошо. Там, в сущности, кода совсем-совсем немного.
                      Всё, что вы говорите, справедливо, но есть одно но. Используя не встроенную реализацию, я сам волен выбирать: хочу — сделаю пул singleton-ом, не хочу — буду использовать несколько экземпляров. Во встроенном пуле — только singleton.
                      Есть много типовых кейсов, когда singleton-пул не катит.
                      TPL эту проблему не решает, пул, к сожалению, по-прежнему один.
                      PS. если есть возможность, как управлять инстансами пулов в TPL — расскажите, пожалуйста, я могу чего-то не знать. Было бы классно, если бы такая возможность была.
            • 0
              добавьте пожалуйста в теги ThreadPool и «потоки»

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