Waitable timer (таймер ожидания)
Таймер ожидания отсутствует в Windows 95 и для его использования необходима Windows 98 или Windows NT 4.0 и выше.
Таймер ожидания переходит в сигнальное состояние по завершении заданного интервала времени. Для его создания используется функция:
function CreateWaitableTimer(
lpTimerAttributes: PSecurityAttributes; // Адрес структуры
// TSecurityAttributes
bManualReset: BOOL; // Задает, будет ли таймер переходить в
// сигнальное состояние по завершении функции
// ожидания
lpTimerName: PChar // Имя объекта
): THandle; stdcall;
Если параметр bManualReset равен TRUE, то таймер после срабатывания функции ожидания остается в сигнальном состоянии до явного вызова SetWaitableTimer, если FALSE - таймер автоматически переходит в несигнальное состояние.
Если lpTimerName совпадает с именем уже существующего в системе таймера – функция возвращает его идентификатор, позволяя использовать объект для синхронизации между процессами. Имя таймера не должно совпадать с именем уже существующих объектов типов event, semaphore, mutex, job или file-mapping.
Идентификатор уже существующего таймера можно получить функцией:
function OpenWaitableTimer(
dwDesiredAccess: DWORD; // Задает права доступа к объекту
bInheritHandle: BOOL; // Задает, может ли объект наследоваться
// дочерними процессами
lpTimerName: PChar // Имя объекта
): THandle; stdcall;
Параметр dwDesiredAccess может принимать следующие значения:
TIMER_ALL_ACCESS Разрешает полный доступ к объекту
TIMER_MODIFY_STATE Разрешает изменять состояние таймера функциями SetWaitableTimer и CancelWaitableTimer
SYNCHRONIZE Только Windows NT – разрешает использовать таймер в функциях ожидания
После получения идентификатора таймера, поток может задать время его срабатывания функцией
function SetWaitableTimer(
hTimer: THandle; // Идентификатор таймера
const lpDueTime: TLargeInteger; // Время срабатывания
lPeriod: Longint; // Период повторения срабатывания
pfnCompletionRoutine: TFNTimerAPCRoutine; // Процедура-обработчик
lpArgToCompletionRoutine: Pointer;// Параметр процедуры-обработчика
fResume: BOOL // Задает, будет ли операционная
// система «пробуждаться»
): BOOL; stdcall;
Рассмотрим параметры подробнее.
lpDueTime
Задает время срабатывания таймера. Время задается в формате TFileTime и базируется на coordinated universal time (UTC), т.е. должно указываться по Гринвичу. Для преобразования системного времени в TFileTime используется функция SystemTimeToFileTime. Если время имеет положительный знак, оно трактуется как абсолютное, если отрицательный – как относительное от момента запуска таймера.
lPeriod
Задает срок между повторными срабатываниями таймера. Если lPeriod равен 0 – таймер сработает один раз.
pfnCompletionRoutine
Адрес функции, объявленной как:
procedure TimerAPCProc(
lpArgToCompletionRoutine: Pointer; // данные
dwTimerLowValue: DWORD; // младшие 32 разряда значения таймера
dwTimerHighValue: DWORD; // старшие 32 разряда значения таймера
); stdcall;
Эта функция вызывается, когда срабатывает таймер, если поток, ожидающий его срабатывания, использует функцию ожидания, поддерживающую асинхронный вызов процедур. В функцию передаются 3 параметра:
• | lpArgToCompletionRoutine – значение, переданное в качестве одноименного параметра в функцию SetWaitableTimer. Приложение может использовать его для передачи в процедуру обработки адреса блока данных, необходимых для её работы |
• | dwTimerLowValue и dwTimerHighValue – соответственно члены dwLowDateTime и dwHighDateTime структуры TFileTime. Они описывают время срабатывания таймера. Время задается в UTC формате (по Гринвичу). |
Если дополнительная функция обработки не нужна, в качестве этого параметра можно передать NIL.
lpArgToCompletionRoutine
Это значение передается в функцию pfnCompletionRoutine при её вызове.
fResume
Определяет необходимость "пробуждения" системы, если на момент срабатывания таймера она находится в режиме экономии электроэнергии (suspended). Если операционная система не поддерживает пробуждение и fResume равно TRUE, функция SetWaitableTimer выполнится успешно, однако последующий вызов GetLastError вернет результат ERROR_NOT_SUPPORTED.
Если необходимо перевести таймер в неактивное состояние, это можно сделать функцией:
function CancelWaitableTimer(hTimer: THandle): BOOL; stdcall;
Эта функция не изменяет состояния таймера и не приводит к срабатыванию функций ожидания и вызову процедур-обработчиков.
По завершении работы объект должен быть уничтожен функцией CloseHandle
Создадим класс, который ожидает в отдельном потоке наступления заданного времени, а затем вызывает процедуру главного потока приложения. Такой класс может использоваться, например, в планировщике заданий. Поскольку таймер ожидания позволяет задавать время срабатывания в абсолютных величинах, отпадает необходимость постоянно анализировать текущее время, используя обычный таймер Windows.
Code: |
unit WaitThread;
interface
uses Classes, Windows;
type TWaitThread = class(TThread) WaitUntil: TDateTime; procedure Execute; override; end;
implementation
uses SysUtils;
procedure TWaitThread.Execute; var Timer: THandle; SystemTime: TSystemTime; FileTime, LocalFileTime: TFileTime; begin Timer := CreateWaitableTimer(NIL, FALSE, NIL); try DateTimeToSystemTime(WaitUntil, SystemTime); SystemTimeToFileTime(SystemTime, LocalFileTime); LocalFileTimeToFileTime(LocalFileTime, FileTime); SetWaitableTimer(Timer, TLargeInteger(FileTime), 0, NIL, NIL, FALSE); WaitForSingleObject(Timer, INFINITE); finally CloseHandle(Timer); end; end;
end. Использовать этот класс можно, например, следующим образом: type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private procedure TimerFired(Sender: TObject); end;
...
implementation
uses WaitThread;
procedure TForm1.Button1Click(Sender: TObject); var T: TDateTime; begin with TWaitThread.Create(TRUE) do begin OnTerminate := TimerFired; FreeOnTerminate := TRUE; // Срок ожидания закончится через 5 секунд WaitUntil := Now + 1 / 24 / 60 / 60 * 5; Resume; end; end;
procedure TForm1.TimerFired(Sender: TObject); begin ShowMessage('Timer fired !'); end; |
Просьба писать ваши замечания, наблюдения и все остальное,
что поможет улучшить предоставляемую информацию на этом сайте.
ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!