Синхронизация потоков в операционной системе Windows, страница 13

Если происходит любое из указанных изменений, дескриптор переходит в сигнальное состояние. Переход дескриптора в сигнальное состояние можно обнаружить при помощи MaitForSingleObject или любого другого аналогичного вызова. Функция FindNextChangeNotification выводит дескриптор из сигнального состояния таким образом, чтобы можно было продолжить слежение за изменениями в каталоге. Если осуществлять слежение за изменениями больше не требуется, следует воспользоваться функцией FindCloseChangeNotification для того, чтобы уничтожить соответствующий дескриптор.

В листинге 4 приведен пример программы, которая осуществляет слежение за изменениями в каталоге C:\SPOOLMSG. Если вы запустите программу, а затем скопируете в этот каталог файл (или уничтожите или переименуете один из содержащихся в этом каталоге файлов), программа выведет на экран окно сообщения, сообщающее об изменениях. Конечно, более сложная программа может определить имя файла (при помощи вызова FindFirst и других связанных с этим вызовов), отобразить его содержимое, после чего уничтожить его.

Листинг 4. Использование оповещения об изменениях

#include <windows.h>

void main()

{

HANDLE spool=FindFirstChangeNotification("c:\\spoolmsg", FALSE,

                                                                       FILE_NOTIFY_CHANGE_FILE_NAME);

while(1) {

          WaitForSingleObject(spool,INFINITE);

          MessageBox(NULL,"Контрольный каталог был изменен",

                                                                                "SPOOLMSG",MB_OK);

          FindNextChangeNotification(spool);

          }

}

Дискриптор консоли

Дискриптор консоли переходит в сигнальное состояние в случае, если в стандартном потоке ввода находятся данные, которые необходимо прочитать. Стандартный дискриптор ввода можно получить несколькими способами. Например, можно обратиться к функции CreateFile и передать ей в качестве имени файла ключевое слово CONIN$ или вызвать функцию GetStdHandlе.

Поначалу слежение за состоянием стандартного дескриптора ввода может показаться бессмысленным. В конце концов, действия, связанные с ожиданием данных, поступающих через стандартный поток ввода, обычно выполняются стандартными функциями C++. Не спешите делать выводы. Слежение за состоянием потока ввода может потребоваться вам при организации перекрывающегося ввода/вывода, о котором речь в следующей лабораторной работе. Мы рассмотрим, каким образом можно ожидать поступления данных через, например, последовательный порт и при этом выполнять какие-либо другие действия.

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

Заключение

Если вы не используете преимуществ многопоточности и многозадачности, значит, вы не используете преимуществ Windows. Освоить методы работы в многопоточной среде относительно несложно, а преимущества многопоточного подхода сложно переоценить. К тому же Windows предлагает обширный набор удобных механизмов, облегчающих взаимодействие потоков и процессов и существенно упрощающих разработку многопоточных приложений.

Выбор метода синхронизации

Зачастую реализовать тот или иной метод синхронизации значительно проще, чем определить, какой из механизмов синхронизации лучшим образом подходит для применения в Вашей программе. Основными типами объектов синхронизации являются события (events), мьютексы (mutexes) и семафоры (semaphores). Каждый из этих объектов обладает своими особенностями, делающими его применение удобным в той или иной ситуации.