Поток. Консольный ввод. Оповещение об изменении в файловой системе.
Поток может ожидать другой поток точно так же, как и другой процесс. Ожидание можно организовать с помощью функций API (как в только что рассмотренном примере), но удобнее это сделать при помощи метода TThread.WaitFor.
Консольный ввод
Консольный ввод (console input) годится для потоков, которые должны ожидать отклика на нажатие пользователем клавиши на клавиатуре. Этот тип ожидания может быть использован в программе дуплексной связи (chat). Один поток при этом будет ожидать получения символов; второй – отслеживать ввод пользователя и затем отсылать набранный текст ожидающему приложению.
Оповещение об изменении в файловой системе
Этот вид объекта ожидания очень интересен и незаслуженно мало известен. Мы рассмотрели практически все варианты того, как один поток может подать сигнал другому. А как получить сигнал от операционной системы? Ну, например, о том, что в файловой системе произошли какие-то изменения? Такой вид оповещения позаимствован из ОС UNIX и доступен программистам, работающим с Win32.
Для организации мониторинга файловой системы нужно использовать три функции – FindFirstChangeNotification, FindNextChangeNotification и FinddoseChangeNotification. Первая из них возвращает дескриптор объекта файлового оповещения, который можно передать в функцию ожидания. Объект активизируется тогда, когда в заданной папке произошли те или иные изменения (создание или уничтожение файла или папки, изменение прав доступа и т. д.). Вторая – готовит объект к реакции на следующее изменение. Наконец, с помощью третьей функции следует закрыть ставший ненужным объект.
Так может выглядеть код метода Execute потока, созданного для мониторинга файловой системы:
var DirName: string; … procedure TSimpleThread.Execute; var r: Cardinal; fn: THandle; begin fn: = FindFirstChangeNotification(pChar(DirName), True, FILEJTOTIFY_CHANGE_FILE_NAME); repeat r: = WaitForSingleObject(fn,2000); if r = WAIT_OBOECT_0 then Synchronize(Forml.UpdateList); if not FindNextChangeNotification(fn) then break; until Terminated; FindCloseChangeNotification(fn); end;
На главной форме должны находиться компоненты, нужные для выбора обследуемой папки, а также компонент TListBox, в который будут записываться имена файлов:
procedure TForml.ButtonlClick(Sender: TObject); var dir: string; begin if SelectDirectory(dir,[],0) then begin Editl.Text: = dir; DirName: = dir; end; end; procedure TForml.UpdateList; var SearchRec: TSearchRec; begin ListBoxl.Clear; FindFirst(Editl.Text+'\*.*', faAnyFile, SearchRec); repeat ListBoxl.Items.Add(SearchRec.Name); until FindNext(SearchRec) <> 0; FindClose(SearchRec); end;
Приложение готово. Чтобы оно стало полнофункциональным, предусмотрите в нем механизм перезапуска потока при изменении обследуемой папки.