Студопедия
Главная страница | Контакты | Случайная страница

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Дополнительные объекты синхронизации

Читайте также:
  1. II. Объекты и сроки прохождения практики
  2. II. Объекты и субъекты криминалистической идентификации. Идентификационные признаки и их классификация.
  3. VI. ЛАБОРАТОРНЫЕ, ДОПОЛНИТЕЛЬНЫЕ МЕТОДЫ ИССЛЕДОВАНИЯ
  4. В ВОДНЫЕ ОБЪЕКТЫ
  5. В Приложении помещают вспомогательные или дополнительные материалы, которые загромождают текст основной части.
  6. Вещи как объекты гражданских прав и их классификация
  7. Виды и объекты инвестиций.
  8. Вопрос 1.Понятие микроэкономики, объекты изучения
  9. Вопрос 17. Понятие качества продукции. Объекты и виды технического контроля качества продукции
  10. Вопрос 2. Объекты страхования.

Некоторые объекты Win32 API не предназначены исключительно для целей синхронизации, однако могут использоваться с функциями синхронизации. Такими объектами являются:

Сообщение об изменении папки (change notification)

Windows позволяет организовать слежение за изменениями объектов файловой системы. Для этого служит функция FindFirstChangeNotification:

function FindFirstChangeNotification(lpPathName: PChar; // Путь к папке, изменения в которой нас // интересуют bWatchSubtree: BOOL; // Задает необходимость слежения за // изменениями во вложенных папках dwNotifyFilter: DWORD // Фильтр событий): THandle; stdcall;

Параметр dwNotifyFilter — это битовая маска из одного или нескольких следующих значений:

FILE_NOTIFY_CHANGE_FILE_NAME Слежение ведется за любым изменением имени файла, в том числе за созданием и удалением файлов
FILE_NOTIFY_CHANGE_DIR_NAME Слежение ведется за любым изменением имени папки, в том числе за созданием и удалением папок
FILE_NOTIFY_CHANGE_ATTRIBUTES Слежение ведется за любым изменением атрибутов
FILE_NOTIFY_CHANGE_SIZE Слежение ведется за изменением размера файлов. Изменение размера происходит при записи в файл. Функция ожидания срабатывает только после успешного сброса дискового кэша
FILE_NOTIFY_CHANGE_LAST_WRITE Слежение ведется за изменением времени последней записи в файл, то есть фактически за любой записью в файл. Функция ожидания срабатывает только после успешного сброса дискового кэша
FILE_NOTIFY_CHANGE_SECURITY Слежение ведется за любыми изменениями дескрипторов защиты

 

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

function FindNextChangeNotification(hChangeHandle: THandle): BOOL; stdcall;

По завершении работы идентификатор должен быть закрыт при помощи функции FindCloseChangeNotification:

function FindCloseChangeNotification(hChangeHandle: THandle): BOOL; stdcall;

Чтобы не блокировать исполнение основного потока программы функцией ожидания, удобно реализовать ожидание изменений в отдельном потоке. Реализуем поток на базе класса TThread. Для того чтобы можно было прервать исполнение потока методом Terminate, необходимо, чтобы функция ожидания, реализованная в методе Execute, также прерывалась при вызове Terminate. Для этого будем использовать вместо WaitForSingleObject функцию WaitForMultipleObjects и прерывать ожидание по событию (event), устанавливаемому в Terminate:

type TCheckFolder = class(TThread) private FOnChange: TNotifyEvent; Handles: array[0..1] of THandle; // Идентификаторы объектов // синхронизации procedure DoOnChange; protected procedure Execute; override; public constructor Create(CreateSuspended: Boolean; PathToMonitor: String; WaitSubTree: Boolean; OnChange: TNotifyEvent; NotifyFilter: DWORD); destructor Destroy; override; procedure Terminate; end; procedure TCheckFolder.DoOnChange; // Эта процедура вызывается в контексте главного потока приложения // В ней можно использовать вызовы VCL, изменять состояние формы, // например перечитать содержимое TListBox, отображающего файлы begin if Assigned(FOnChange) then FOnChange(Self); end; procedure TCheckFolder.Terminate; begin inherited; // Вызываем TThread.Terminate, устанавливаем // Terminated = TRUE SetEvent(Handles[1]); // Сигнализируем о необходимости // прервать ожидание end; constructor TCheckFolder.Create(CreateSuspended: Boolean; PathToMonitor: String; WaitSubTree: Boolean; OnChange: TNotifyEvent; NotifyFilter: DWORD); var BoolForWin95: Integer; begin // Создаем поток остановленным inherited Create(TRUE); // Windows 95 содержит не очень корректную реализацию функции // FindFirstChangeNotification. Для корректной работы необходимо, // чтобы: // - lpPathName - не содержал завершающего слэша "\" для // некорневого каталога // - bWatchSubtree - TRUE должен передаваться как BOOL(1) if WaitSubTree then BoolForWin95:= 1 else BoolForWin95:= 0; if (Length(PathToMonitor) > 1) and (PathToMonitor[Length(PathToMonitor)] = ‘\’) and (PathToMonitor[Length(PathToMonitor)-1] <> ‘:’) then Delete(PathToMonitor, Length(PathToMonitor), 1); Handles[0]:= FindFirstChangeNotification(PChar(PathToMonitor), BOOL(BoolForWin95), NotifyFilter); Handles[1]:= CreateEvent(NIL, TRUE, FALSE, NIL); FOnChange:= OnChange; // И, при необходимости, запускаем if not CreateSuspended then Resume; end; destructor TCheckFolder.Destroy; begin FindCloseChangeNotification(Handles[0]); CloseHandle(Handles[1]); inherited; end; procedure TCheckFolder.Execute; var Reason: Integer; Dummy: Integer; begin repeat // Ожидаем изменения в папке либо сигнала о завершении // потока Reason:= WaitForMultipleObjects(2, @Handles, FALSE, INFINITE); if Reason = WAIT_OBJECT_0 then begin // Изменилась папка, вызываем обработчик в контексте // главного потока приложения Synchronize(DoOnChange); // И продолжаем поиск FindNextChangeNotification(Handles[0]); end; until Terminated; end;

 

Поскольку метод TThread.Terminate не виртуальный, этот класс нельзя использовать с переменной типа TThread, так как в этом случае будет вызываться метод Terminate класса TThread, который не может прервать ожидания, и поток будет выполняться до изменения в папке, за которой ведется слежение.

Устройство стандартного ввода с консоли (console input)

Идентификатор стандартного устройства ввода с консоли, полученный при помощи вызова функции GetStdHandle(STD_INPUT_HANDLE), можно использовать в функциях ожидания. Он находится в сигнальном состоянии, если очередь ввода консоли не пустая, и в несигнальном — если пустая. Это позволяет организовать ожидание ввода символов или при помощи функции WaitForMultipleObjects совместить его с ожиданием каких-либо других событий.

Задание (Job)

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

Процесс (Process)

Идентификатор процесса, полученный при помощи функции CreateProcess, переходит в сигнальное состояние по завершении процесса, что позволяет организовать ожидание завершения процесса, например, при запуске из приложения внешней программы:

var PI: TProcessInformation; SI: TStartupInfo;... FillChar(SI, SizeOf(SI), 0); SI.cb:= SizeOf(SI); Win32Check(CreateProcess(NIL, 'COMMAND.COM', NIL, NIL, FALSE, 0, NIL, NIL, SI, PI)); // Задерживаем исполнение программы до завершения процесса WaitForSingleObject(PI.hProcess, INFINITE); CloseHandle(PI.hProcess); CloseHandle(PI.hThread);

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

Поток (thread)

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




Дата добавления: 2014-12-19; просмотров: 86 | Поможем написать вашу работу | Нарушение авторских прав




lektsii.net - Лекции.Нет - 2014-2025 год. (0.008 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав