Центр справки и настройки Windows XP 3.8


Процессы в Windows - часть 9


/p>

Замечание. В этом примере мы считаем, что сами процедуры добавления элемента в очередь и удаления из очереди безопасны с точки зрения многопоточности. Не будем пока касаться деталей их реализации. Подробнее мы рассмотрим это в примере 9.

События.

События (Event), также как и мьютексы имеют два состояния - установленное и сброшенное. События бывают со сбросом вручную и с автосбросом. Когда поток дождался (wait-функция вернула управление) события с автосбросом, такое событие автоматически сбрасывается. В противном случае событие нужно сбрасывать вручную, вызвав функцию ResetEvent(). Допустим, сразу несколько потоков ожидают одного и того же события, и событие сработало. Если это было событие с автосбросом, то оно позволит работать только одному потоку (ведь сразу же после возврата из его wait-функции событие сбросится автоматически!), а остальные потоки останутся ждать. Если же это было событие со сбросом вручную, то все потоки получат управление, а событие так и останется в установленном состоянии, пока какой-нибудь поток не вызовет ResetEvent().

Пример 5. Вот еще один пример многопоточного приложения. Программа имеет два потока; один готовит данные, а второй отсылает их на сервер. Разумно распараллелить их работу. Здесь потоки должны работать по очереди. Сначала первый поток готовит порцию данных. Потом второй поток отправляет ее, а первый тем временем готовит следующую порцию и т.д. Для такой синхронизации понадобится два event'а с автосбросом.

unsigned __stdcall CaptureThreadFunc( void * arg) // Поток, готовящий данные

{ while (bSomeCondition) { WaitForSingleObject(m_hEventForCaptureTh,INFINITE); // Ждем своего события

... // Готовим данные

SetEvent(hEventForTransmitTh); // Разрешаем работать второму потоку

} _endthreadex( 0 ); return 0; };

unsigned __stdcall TransmitThreadFunc( void * arg) // Поток, отсылающий данные.

{ while (bSomeCondition) { WaitForSingleObject(m_hEventForTransmitTh,INFINITE); // Ждем своего события

... // Данные готовы, формируем из них пакет для отправки

SetEvent(hEventForCaptureTh); // Разрешаем работать первому потоку, а сами...

... // отправляем пакет

} _endthreadex( 0 ); return 0; };

int main(int argc, char* argv[]) // Основной поток

{ // Создаем два события с автосбросом, со сброшенным начальным состоянием

hEventForCaptureTh = CreateEvent(NULL,FALSE,FALSE,NULL); hEventForTransmitTh = CreateEvent(NULL,FALSE,FALSE,NULL);

// Создаем потоки

hCaptureTh = (HANDLE)_beginthreadex( NULL, 0, &CaptureThreadFunc, 0, 0,&uTh1); hTransmitTh = (HANDLE)_beginthreadex( NULL, 0, &TransmitThreadFunc, 0, 0,&uTh2); // Запускаем первый поток

SetEvent(hEventForCaptureTh);

.... }

<


Начало  Назад  Вперед



Книжный магазин