Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции-ТРПС.doc
Скачиваний:
13
Добавлен:
15.11.2018
Размер:
810.5 Кб
Скачать

12.5. Общая схема взаимодействия потоков

Рассмотрим общую схему взаимодействия главного и рабочего потоков. Определим структуру SWT, которая будет передаваться в функцию рабочего потока как параметр:

struct SWT { HANDLE hevBeg; // событие начала HANDLE hevEnd; // событие завершения CRITICAL_SECTION cs; // дополнительные поля };

Структура, помимо полей, определяемых решаемой задачей, содержит два дескриптора событий и критическую секцию.

В главном потоке объявляются две статические переменные swt и hThread, а также проводится инициализация критической секции и создание объектов событий для управления рабочим потоком. Оба события используют "ручное" изменение состояния и первоначально установлены в "сброшено".

static SWT swt; static HANDLE hThread;

swt.hevBeg = CreateEvent(NULL, TRUE, FALSE, NULL); swt.hevEnd = CreateEvent(NULL, TRUE, FALSE, NULL); InitializeCriticalSection(&swt.cs);

Затем запускается рабочий поток с обслуживающей функцией ThreadFunc(), которой в качестве параметра передается указатель на структуру swt.

hThread = CreateThread(NULL,0, ThreadFunc,&swt,0,&idThread);

После этого, возможно в другом обработчике функции главного окна приложения, устанавливается событие hevBeg, что является сигналом рабочему потоку к началу исполнения своего кода.

SetEvent(swt.hevBeg); // Событие установлено

Теперь рассмотрим функцию рабочего потока

DWORD WINAPI ThreadFunc (LPVOID pData) { // преобразуем указатель SWT* pswt = (SWT*)pData; // бесконечно ожидаем наступления события /*1*/ WaitForSingleObject(pswt->hevBeg, INFINITE);

// продолжаем цикл пока не установлено // события завершения рабочего потока /*2*/ while (WaitForSingleObject(pswt->hevEnd, 0) != WAIT_OBJECT_0) { // вводим критическую секцию и ждем когда // остальные потоки будут заблокированы EnterCriticalSection(&pswt->cs); // некие действия // в "монопольном" режиме // сбрасываем критическую секцию LeaveCriticalSection(&pswt->cs); } // сбрасываем событие ResetEvent(pswt->hEvEnd); // выход из функции автоматически // завершает рабочий поток return 0; }

В цикле, помеченном через /*1*/, функция рабочего потока будет находиться до тех пор, пока главный поток не установит событие hevBeg. Цикл, помеченный /*2*/, организован иным образом. Функция ожидания только проверяет состояние события hevEnd. Если оно не установлено, то выполняется тело цикла, в противном случае – цикл заканчивается, что ведет к выходу из функции рабочего потока и завершению самого потока.

Вернемся в главный поток. Для того, чтобы завершить рабочий поток устанавливается событие hevEnd, после чего процесс ожидает момента его сброса в рабочем потоке.

SetEvent(swt.hevEnd); while (WaitForSingleObject(swt.hevEnd, 200) == WAIT_OBJECT_0); // в данный момент рабочий поток завершен

Затем выполняется закрытие объектов

CloseHandle(hThread); CloseHandle(swt.hevBeg); CloseHandle(swt.hevEnd); DeleteCriticalSection(&swt.cs);

Используете функцию ожидания Sleep(), только для рабочих потоков. При ее применении в главном потоке он блокируется и не обрабатывает поступающие сообщения.