лабараторная работа. Теория_к_лабораторным. 1. Применение параллельных вычислений
Скачать 0.7 Mb.
|
7. Диспетчеризация потоков на C#Это последний и, наверное, самый интересный и наглядный пример программирования на C# с использованием параллельных вычислений. Если на предыдущем шаге была имитация гонок, то этот шаг скорее похож на имитацию процесса регулирования дорожного движения. Диспетчеризация потоков – это управление процессами выделения потокам вычислительных ресурсов, их регламентация и мониторинг за ходом выполнения параллельных вычислений. Как я уже говорил, используя экземпляры классов Thread можно блокировать выбранный поток или вообще завершить его работу. Также, ход выполнения нескольких параллельных потоков можно синхронизировать, заставляя одни из них дожидаться окончания выполнения других с использованием метода Join(). На этом шаге будут рассмотрены способы опосредованной диспетчеризации потоков, которые можно применять не только при работе с экземплярами класса Thread, но также и с потоками из пула потоков. Пример программы, использующей диспетчеризацию потоков с использованием событий и семафоров. СобытияИмеются в виду не те события, которые используются для организации обратных вызовов, а “маяки”, которые способны приостанавливать работу потоков и подавать им сигналы для возобновления прерванных вычислений. “Устанавливаются” эти “маяки” непосредственно в код с использованием экземпляров классовAutoResetEvent и ManualResetEvent. Если поток в ходе вычислений встречает вызов метода WaitOne() экземпляра события, то дальнейшие действия могут развиваться по одному из следующих сценариев: Поток продолжает работу, если событие подает сигнал, позволяющий беспрепятственно “следовать дальше”. Это означает, что событие находится всигнальном состоянии. Поток приостанавливает работу, если событие находится в несигнальном состоянии. Работа потока может быть продолжена, как только событие переходит в сигнальное состояние. Почему "может быть продолжена", а не "будет продолжена" объясняется далее. Есть два типа события: с ручным и автоматическим режимом перехода в несигнальное состояние, останавливающее потоки. Их разница в следующем: события с “автоматическим перезапуском”, находясь в несигнальном состоянии, “ловят” все потоки, ход выполнения которых натыкается на метод WaitOne(), а после перехода в сигнальное состояние “отпускают” только один из них (любой) и сразу же автоматически снова переходят в несигнальное состояние. События с “ручным перезапуском” также ловят всех, но, будучи переведенными в сигнальное состояние вызовом метода Set(), отпускают тоже всех, пока их принудительно не вернут в несигнальное состояние вызовом метода Reset(). Поэкспериментировать с этими видами событий можно на примере демонстрационной программы. Для запуска примера необходимо нажать кнопку [Старт]. В отличие от предыдущего примера сразу ничего происходить не будет. Если выбран ручной режим, то после нажатия на [Старт] необходимо нажать [Вперед], и потоки “побегут” к финишу, пока не будет нажата кнопка [Стоп]. Чередуя [Стоп]и [Вперед] вы будете останавливать и возобновлять работу всех потоков. Если выбран автоматический режим, то кнопка [Стоп] становится неактивной, а для того чтобы что-то происходило нужно постоянно нажимать на кнопку [Вперед], поскольку каждый раз будет "оживать" лишь один поток и после "короткой перебежки" снова "замирать". |