Страница 415 из 502
Ниже приведены конструкторы классов ManualResetEvent и AutoResetEvent.
<b>public ManualResetEvent(bool initialState)</b>
<b>public AutoResetEvent(bool initialState)</b>
Если в обеих формах параметр initialState имеет логическое значение true, то о событии первоначально уведомляется. А если он имеет логическое значение false, то о событии первоначально не уведомляется.
Применяются события очень просто. Так, для события типа ManualResetEvent порядок применения следующий. Поток, ожидающий некоторое событие, вызывает метод WaitOne() для событийного объекта, представляющего данное событие. Если событийный объект находится в сигнальном состоянии, то происходит немедленный возврат из метода WaitOne(). В противном случае выполнение вызывающего потока приостанавливается до тех пор, пока не будет получено уведомление о событии. Как только событие произойдет в другом потоке, этот поток установит событийный объект в сигнальное состояние, вызвав метод Set(). Поэтому метод Set() следует рассматривать как уведомляющий о том, что событие произошло. После установки событийного объекта в сигнальное состояние произойдет немедленный возврат из метода WaitOne(), и первый поток возобновит свое выполнение. А в результате вызова метода Reset() событийный объект возвращается в несигнальное состояние.
Событие типа AutoResetEvent отличается от события типа ManualResetEvent лишь способом установки в исходное состояние. Если для события типа ManualResetEvent событийный объект остается в сигнальном состоянии до тех пор, пока не будет вызван метод Reset(), то для события типа AutoResetEvent событийный объект автоматически переходит в несигнальное состояние, как только поток, ожидающий это событие, получит уведомление о нем и возобновит свое выполнение. Поэтому если применяется событие типа AutoResetEvent, то вызывать метод Reset() необязательно.
В приведенном ниже примере программы демонстрируется применение события типа ManualResetEvent.
<b>// Использовать событийный объект, устанавливаемый</b>
<b>// в исходное состояние вручную.</b>
<b>using System;</b>
<b>using System.Threading;</b>
<b>// Этот поток уведомляет о том, что событие передано его конструктору,</b>
<b>class MyThread {</b>
<b> public Thread Thrd;</b>
<b> ManualResetEvent mre;</b>
<b> public MyThread(string name, ManualResetEvent evt) {</b>
<b> Thrd = new Thread(this.Run);</b>
<b> Thrd.Name = name;</b>
<b> mre = evt;</b>
<b> Thrd.Start();</b>
<b> }</b>
<b> // Точка входа в поток,</b>
<b> void Run() {</b>
<b> Console.WriteLine("Внутри потока " + Thrd.Name);</b>
<b> for(int i=0; i<5; i++) {</b>
<b> Console.WriteLine(Thrd.Name);</b>
<b> Thread.Sleep(500) ;</b>
<b> }</b>
<b> Console.WriteLine(Thrd.Name + " завершен!");</b>
<b> // Уведомить о событии,</b>
<b> mre.Set();</b>
<b> }</b>
<b>}</b>
<b>class ManualEventDemo {</b>
<b> static void Main() {</b>
<b> ManualResetEvent evtObj = new ManualResetEvent(false);</b>
<b> MyThread mt1 = new MyThread("Событийный Поток 1", evtObj);</b>
<b> Console.WriteLine("Основной поток ожидает событие.");</b>
<b> // Ожидать уведомления о событии.</b>
<b> evtObj.WaitOne();</b>
<b> Console.WriteLine("Основной поток получил " +</b>
<b> "уведомление о событии от первого потока.");</b>
<b> // Установить событийный объект в исходное состояние.</b>
<b> evtObj.Reset();</b>
<b> mt1 = new MyThread("Событийный Поток 2", evtObj);</b>
<b> // Ожидать уведомления о событии.</b>
<b> evtObj.WaitOne();</b>
<b> Console.WriteLine("Основной поток получил " +</b>
<b> "уведомление о событии от второго потока.");</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения рассматриваемой здесь программы, хотя у вас он может оказаться несколько иным.
<b>Внутри потока Событийный Поток 1</b>