Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Пул потоков CLR

Пул потоков CLR

Заключительной темой нашего обсуждения в этой плаве, посвященной потокам, будет пул потоков CLR. При асинхронном вызове типов с помощью делегатов (посредством метода BeginInvoke()) нельзя сказать, что среда CLR буквально создает совершенно новый поток. В целях эффективности метод BeginInvoke() делегата использует пул (динамическую область) рабочих потоков, поддерживаемых средой выполнения. Чтобы позволить вам взаимодействовать с этим пулом рабочих потоков, пространство имен System.Threading предлагает тип класса ThreadPool.

Чтобы поставить вызов метода в очередь для обработки рабочим потоком из пула, используйте метод ThreadPool.QueueUserWorkItem(). Этот метод является перегруженным, чтобы вдобавок к экземпляру делегата WaitCallback имелась возможность указать необязательный System.Objеct для пользовательских данных состояния.

public sealed class ThreadPool {
 …
 public static bool QueueUserWorkItem(WaitCallback callBack);
 public static bool QueueUserWorkItem(WaitCallback callBack, object state);
}

Делегат WaitCallback может указывать на любой метод, имеющий один параметр System.Object (для представления необязательных данных состояния) и не возвращающий ничего. Если при вызове QueueUserWorkItem() вы не предложите System.Object, среда CLR автоматически передаст значение null. Для иллюстрации методов очереди при использовании пула потоков CLR давайте рассмотрим следующую программу, в которой снова используется тип Printer. Но на этот раз мы не будем создавать массив типов Thread вручную, а свяжем метод PrintNumbers() с членами пула.

class Program {
 static void Main(string[] args) {
  Console.WriteLine("Старт главного потока. ThreadID = {0}", Thread.CurrentThread.GetHashCode());
  Printer p = new Printer();
  WaitCallback workItem = new WaitCallback(PrintTheNumbers);
  // Очередь из 10 вызовов метода.
  for (int i = 0; i ‹ 10; i++) {
   ThreadPool.QueueUserWorkItem(workItem, p);
  }
  Console.WriteLine("Все задачи в очереди");
  Console.ReadLine();
 }
 static void PrintTheNumbers(object state) {
  Printer task = (Printer)state;
  task.PrintNumbers();
 }
}

Здесь вы можете спросить, разве выгодно использовать поддерживаемый средой CLR пул потоков вместо явного создания объектов Thread? Тогда рассмотрите следующие главные преимущества использования пула.

• Пул потоков управляет потоками эффективнее, поскольку минимизируется число потоков, которые приходится создавать, запускать и останавливать.

• При использовании пула потоков вы можете сосредоточиться на своей конкретной задаче, не отвлекаясь на вопросы инфраструктуры потоков приложения.

Однако управление потоками "вручную" может оказаться предпочтительнее, например, в следующих случаях.

• Если требуется создавать приоритетные потоки или устанавливать приоритеты потоков. Потоки, помещенные в пул, всегда являются фоновыми потоками с обычным уровнем приоритета (ThreadPriority.Normal).

• Если требуется создать поток с фиксированным идентификатором, чтобы име-лаcь возможность завершить, приостановить или обнаружить его по имени.

Исходный код. Проект ThreadPoolApp размещён в подкаталоге, соответствующем главе 14.

На этом наш экскурс в многопоточное программирование .NET завершается. Пространство имен System.Threading, без сомнения, определяет множество других типов, кроме тех, которые смогли уместиться в рамках обсуждения данной главы. Но сейчас вы имеете прочный фундамент, который позволит вам расширять свой знания.

Оглавление книги


Генерация: 3.728. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз