Вопрос по Курсу: "Параллельное программирование с использованием MS VisualStudia 2010". При компиляции Самостоятельного задания (одновременная отрисовка прямоугольников, эллипсов и выдача в текст-бокс случайного числа) среда предупреждает: suspend - устаревшая команда; примените monitor, mutex и т.п. Создаётся впечатление, что Задание создано в более поздней среде, чем VS 2010. |
Многопоточность в .NET Framework
Пул потоков CLR
При использовании различных коротких задач, подлежащие выполнению, можно заранее создать набор потоков и затем просто отправлять соответствующие запросы, когда наступает очередь для их выполнения, т.е. если количество этих потоков автоматически увеличивалось с ростом необходимости в этих потоках и уменьшалось при возникновении потребности в освобождении ресурсов.
Для управления списком потоков предусмотрен класс ThreadPool, который по мере необходимости уменьшает и увеличивает количество потоков в пуле до максимально допустимого значения. Значение максимально допустимого количества потоков в пуле может изменяться. В случае двуядерного ЦП оно по умолчанию составляет 1023 рабочих потоков и 1000 потоков ввода-вывода.
Для того, чтобы запросить поток из пула для обработки вызова метода, можно использовать метод QueueUserWorkItem(). Этот метод перегружен, чтобы в дополнение к экземпляру делегата WaitCallback позволить указывать необязательный параметр System.Object для специальных данных состояния.
Ниже приведен пример приложения, в котором сначала читается и выводится на консоль информация о максимальном количестве рабочих потоков и потоков ввода-вывода. Затем в цикле for метод JobForAThread() назначается потоку из пула потоков за счет вызова метода ThreadPool.QueueUserWorkltem() и передачи делегата типа WaitCallback. Пул потоков получает этот запрос и выбирает из пула один из потоков для вызова метода. Если пул еще не существует, он создается и запускается первый поток:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ThreadingPools { class Program { static void Main(string[] args) { for (int i = 0; i < 5; i++) { ThreadPool.QueueUserWorkItem(JobForAThread); Thread.Sleep(2000); } Console.ReadLine(); } static void JobForAThread(object state) { for (int i = 0; i < 10; i++) { Console.WriteLine("Цикл {0}, выполняется внутри потока {1}", i, Thread.CurrentThread.ManagedThreadId); Thread.Sleep(10); } } } }
Результат выполнения работ программы представлен на Рис. 4.1.
- Пул потоков управляет потоками эффективно, уменьшая количество создаваемых, запускаемых и останавливаемых потоков.
- Используя пул потоков, можно сосредоточиться на решении задачи, а не на инфраструктуре потоков приложения.
Пулы потоков очень просты в применении, однако обладают рядом ограничений, которые перечислены ниже:
- Все потоки в пуле потоков являются фоновыми. В случае завершения работы всех приоритетных потоков в процессе работа всех фоновых потоков тоже останавливается. Сделать поток из пула приоритетным не удастся.
- Нельзя изменять приоритет или имя находящего в пуле потока. Все потоки в пуле представляют собой потоки многопоточного апартамента (multi-threaded apartment - МТА), а многие СОМ-объекты требуют использования потоков однопоточного апартамента (single-threaded apartment - STA).
- Потоки в пуле подходят для выполнения только коротких задач. Если необходимо, чтобы поток функционировал все время (как, например, поток средства проверки орфографии в Word), его следует создавать с помощью класса Thread.
- Нельзя создавать потоки с фиксированной идентичностью (Чтобы можно было прерывать их или находить по имени).