Визуальное программирование и MFC

       

Работа с объектами событий


Объект событие используется для оповещения процесса или потока о том, сто произошло некоторое событие. Для работы с такими объектами предназначен класс CEvent. Конструктор класса имеет следующий прототип:

CEvent( BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );

Значение первого параметра определяет начальное состояние объекта. Если оно равно TRUE, то объект событие установлен (событие произошло), а если FALSE, то объект не установлен или сброшен (событие не произошло).

Второй параметр указывает, каким образом состояние объекта будет изменяться при выполнении события. Если значение параметра равно TRUE (не ноль), то объект может быть сброшен только путем вызова метода ResetEvent класса CEvent. В противном случае объект автоматически сбрасывается после предоставления блокированному потоку доступа к ресурсу.

Третий параметр конструктора указывает на строку, содержащую имя объекта события. Поименованные объекты события становятся системными объектами и могут использоваться другими процессами. Когда два процесса вызывают объекты события с одинаковыми именами, обоим процессам будет предоставлен один и тот же объект - это позволяет синхронизировать процессы. Вместо имени строки можно указать NULL - в этом случае объект события будет локализован внутри одного процесса.

Последний параметр конструктора является указателем на набор атрибутов прав доступа, связанный с объектом события. Если этот параметр равен NULL, то объект событие наследует данный набор у вызвавшего его потока.

Когда объект событие создан, то поток, ожидающий данное событие, должен с помощью этого объекта создать объект типа CSingleLock, для которого затем следует вызвать метод Lock. При этом выполнение данного потока останавливается до тех пор, пока не произойдет ожидаемое событие.

Для сигнализации о том, что событие произошло, предназначена функция SetEvent класса CEvent.

При вызове данной функции первый поток, ожидающий событие, выйдет из остановленного состояния (вызванный им метод Lock завершится и продолжит свое выполнение.


При работе с программным объектом события необходимо вызывать метод ResetEvent класса CEvent всякий раз, когда поступил сигнал о выполнении события. После его вызова соответствующий объект будет сброшен.

Чтобы продемонстрировать вышесказанное, заменим в предыдущем примере семафор на объект событие. В этой версии функция MyThread1 будет блокирована до тех пор, пока функция MyThread2 не завершится и не сигнализирует о своем завершении. Таким образом, завершение функции MyThread2 является событием, которое ожидает MyThread1:

class CExampleView : public CView { protected: // 1. событие не установлено; 2. сброс его будет автоматическим CEvent event; // другие описания класса ...….. }; .......... UINT MyThread1(LPVOID pParam); UINT MyThread2(LPVOID pParam); void CExampleView::OnStart() { AfxBeginThread(MyThread1,this); AfxBeginThread(MyThread2,this; } UINT MyThread1(LPVOID pParam) { CExampleView *ptrView=(CExampleView *)pParam; CSingleLock syncObj(&(ptrView->event)); ....... syncObj.Lock(); // ожидание события действия, выполняемые после события syncObj.Unlock(); // освобождение объекта события ....... return 0; } UINT MyThread2(LPVOID pParam) { CExampleView *ptrView=(CExampleView *)pParam; ....... ptrView->event.SetEvent(); // сигнализирует о событии return 0; }

Как уже говорилось, объектами синхронизации являются не только семафоры и объекты события, а и критические разделы и исключающие семафоры. Их использование во многом похоже на рассматриваемые выше действия с семафорами и объектами событие. Стоит только отметить, что в некоторых ситуациях использование критических разделов позволяет более эффективно организовать работу с потоками.


Содержание раздела