Выбрать главу

Методы Wait (), Pulse () и PulseAll () определены в классе Monitor и могут вызываться только из заблокированного фрагмента блока. Они применяются следующим образом. Когда выполнение потока временно заблокировано, он вызывает метод Wait (). В итоге поток переходит в состояние ожидания, а блокировка с соответствующего объекта снимается, что дает возможность использовать этот объект в другом потоке. В дальнейшем ожидающий поток активизируется, когда другой поток войдет в аналогичное состояние блокировки, и вызывает метод Pulse () или PulseAll (). При вызове метода Pulse () возобновляется выполнение первого потока, ожидающего своей очереди на получение блокировки. А вызов метода PulseAll () сигнализирует о снятии блокировки всем ожидающим потокам.

Ниже приведены две наиболее часто используемые формы метода Wait ().

public static bool Wait(object obj)

public static bool Wait(object obj, int миллисекунд_простоя)

В первой форме ожидание длится вплоть до уведомления об освобождении объекта, а во второй форме — как до уведомления об освобождении объекта, так и до истечения периода времени, на который указывает количество миллисекунд_простоя. В обеих формах obj обозначает объект, освобождение которого ожидается.

Ниже приведены общие формы методов Pulse () и PulseAll ():

public static void Pulse(object obj) public static void PulseAll(object obj)

где obj обозначает освобождаемый объект.

Если методы Wait(),Pulse() nPulseAll() вызываются из кода, находящегося за пределами синхронизированного кода, например из блока lock, то генерируется исключение SynchronizationLockException.

Пример использования методов Wait () и Pulse ()

Для того чтобы стало понятнее назначение методов Wait () и Pulse (), рассмотрим пример программы, имитирующей тиканье часов и отображающей этот процесс на экране словами "тик" и "так". Для этой цели в программе создается класс TickTock, содержащий два следующих метода: Tick () иТоск(). Метод Tick () выводит на экран слово "тик", а метод Тоск () — слово "так". Для запуска часов далее в программе создаются два потока: один из них вызывает метод Tick (), а другой — метод Тоск (). Преследуемая в данном случае цель состоит в том, чтобы оба потока выполнялись, поочередно выводя на экран слова "тик" и "так", из которых образуется повторяющийся ряд "тик-так", имитирующий ход часов/

using System;

using System.Threading;

class TickTock {

object lockOn = new object (); public void Tick(bool running) { lock(lockOn) {

if(!running) { // остановить часы ‘Monitor.Pulse(lockOn); // уведомить любые ожидающие потоки return;

}

Console.Write("тик ");

Monitor.Pulse(lockOn); // разрешить выполнение метода Tock() Monitor.Wait(lockOn);    // ожидать завершения метода Tock()

}

}

public void Tock(bool running) { lock(lockOn) {

if(!running) { // остановить часы

Monitor.Pulse(lockOn); // уведомить любые ожидающие потоки return;

}

Console.WriteLine("так");

Monitor.Pulse(lockOn); // разрешить выполнение метода Tick() Monitor.Wait(lockOn);    // ожидать завершения метода Tick()

}

}

}

class MyThread {

public Thread Thrd;

TickTock ttOb;

// Сконструировать новый поток.

public MyThread(string name, TickTock tt) {

Thrd = new Thread(this.Run); ttOb = tt;

Thrd.Name = name;

Thrd.Start();    '

}

// Начать выполнение нового потока, void Run() {

if(Thrd.Name == "Tick") {

for(int i=0; i<5; i++) ttOb.Tick(true); ttOb.Tick(false) ;

}

else {

for(int i=0; i<5; i++) ttOb.Tock(true); ttOb.Tock(false);

class TickingClock { static void Main() {

TickTock tt = new TickTock ();

MyThread mtl = new MyThread("Tick", tt);

MyThread mt2 = new MyThread("Tock", tt) ; mtl.Thrd.Join(); mt2.Thrd.Join();

Console.WriteLine("Часы остановлены");

}

}

Ниже приведен результат выполнения этой программы.

тик так тик так тик так тик так тик так

Часы остановлены