Общая рекомендация № 3
Что это означает из Общей рекомендации № 3?
Не контролируйте выполнение рабочих потоков из вашей основной программы (например, используя события). Вместо этого спроектируйте свою программу так, чтобы рабочие потоки отвечали за ожидание, пока работа не стала доступной, ее выполнение и уведомление других частей вашей программы, когда они будут завершены. Если ваши рабочие потоки не блокируются, рассмотрите возможность использования потоков пула потоков. Monitor.PulseAll полезен в ситуациях, когда рабочие потоки блокируются.
Может кто-нибудь объяснить примерами, пожалуйста?
- Источник: MSDN - Лучшие практики управления потоками
3 ответа
Ну, в принципе, есть два способа, которыми вы можете распределить работу между рабочими потоками. Первый - хранить рабочие элементы в очереди. Когда у вас есть работа, вы помещаете ее в очередь и подаете сигнал рабочим. Ваши рабочие потоки будут выглядеть примерно так:
while( !quit ) {
WaitForWork();
GetWorkItem();
ExecuteWorkItem();
}
Это подход, который вы должны использовать, согласно рекомендации.
Другой подход - поддерживать очередь работников. Когда у вас есть работа, которую вам нужно выполнить, вы забираете работника из очереди (или создаете его, если он пуст) и приказывает ему запустить элемент. Этот второй подход более сложен для кодирования и, как правило, менее эффективен.
Я понимаю, что это означает, что вы не должны вручную создавать рабочие потоки для обработки задач (например, сохранять файл), а иметь систему на месте (или использовать ThreadPool.QueueUserWorkItem), где вы можете ставить в очередь задачу / задание и существующего работника ожидает прибытия задачи (возможно, с использованием монитора Wait или AutoResetEvent). Делая это таким образом, вы можете повторно использовать потоки, вместо того, чтобы постоянно создавать и уничтожать их.
.NET 4.0 имеет новый встроенный класс Task с кучей поддерживающих классов, чтобы упростить этот стиль программирования, чтобы вам не приходилось изобретать его заново в каждом проекте.
Я думаю, что эта рекомендация также может относиться к созданию потока, а затем многократно вызывать такие методы, как Suspend
а также Resume
на нем, чтобы контролировать, когда он работает.
Обычно считается лучшей формой, чтобы поток выполнял while
цикл, который содержит какой-то блокирующий примитив (например, ManualResetEvent
или некоторый подобный примитив), чтобы сигнализировать потоку, когда есть больше работы, которая будет сделана.