Лекции.Орг


Поиск:




Категории:

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

 

 

 

 


Таймеры ожидания




Windows NT поддерживает таймеры ожидания (waitable timers), являющихся одним из типов объектов ядра, осуществляющих ожидание.

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

Таймер ожидания может быть либо синхронизирующим (synchronization timer), либо сбрасываемым вручную уведомляющим (manual-reset notification timer) таймером. Синхронизирующий таймер связывается с функцией косвенного вызова, аналогичной процедуре завершения расширенного ввода/вывода, тогда как для синхронизации по сбрасываемому вручную уведомляющему таймеру используется функция ожидания.

Для начала потребуется создать дескриптор таймера, используя для этого функцию CreateWaitableTimer.

HANDLE CreateWaitableTimer(LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCTSTR lpTimerName);

Второй параметр, bManualReset, определяет, таймер какого типа должен быть создан — синхронизирующий или уведомляющий. В программе 14.3 используется синхронизирующий таймер, но, изменив комментарии и настройку параметра, вы легко превратите его в уведомляющий таймер. Заметьте, что существует также функция OpenWaitableTimer, которая может использовать необязательное имя, предоставляемое третьим аргументом.

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

BOOL SetWaitableTimer(HANDLE hTimer, const LARGE_INTEGER *pDueTime, LONG IPeriod, PTIMERAPCROUTINE pfnCompletionRoutine, LPVOID lpArgToCompletionRoutine, BOOL fResume);

hTimer — действительный дескриптор таймера, созданного с использованием функции CreateWaitableTimer.

Второй параметр, на который указывает указатель pDueTime, может принимать либо положительные значения, соответствующие абсолютному времени, либо отрицательные, соответствующие относительному времени, причем фактические значения выражаются в единицах времени длительностью 100 наносекунд, а их формат описывается структурой FILETIME. Переменные типа FILETIME были введены в главе 3 и уже использовались нами в главе 6 в программе timep (программа 6.2).

Величина интервала между сигналами, указываемая в третьем параметре, выражается в миллисекундах. Если это значение установлено равным 0, то таймер переводится в сигнальное состояние только один раз. При положительных значениях этого параметра таймер является периодическим и срабатывает периодически до тех пор, пока его действие не будет прекращено вызовом функции CancelWaitableTimer. Отрицательные значения указанного интервала не допускаются.

Четвертый параметр, pfnCompletionRoutine, применяется в случае синхронизирующего таймера и указывает адрес процедуры завершения, которая вызывается при переходе таймера в сигнальное состояние и при условии, что поток переходит в состояние дежурного ожидания. При вызове этой процедуры в качестве одного из аргументов используется указатель, определяемый пятым параметром, plArgToComplretionRoutine.

Установив синхронизирующий таймер, вы можете перевести поток в состояние дежурного ожидания путем вызова функции SleepEx, чтобы обеспечить возможность вызова процедуры завершения. В случае сбрасываемого вручную уведомляющего таймера следует организовать ожидание перехода дескриптора таймера в сигнальное состояние. Дескриптор будет оставаться в сигнальном состоянии до следующего вызова функции SetWaitableTimer. Полная версия программы 14.3, находящаяся на Web-сайте, предоставляет вам возможность проводить собственные эксперименты, используя таймер выбранного типа в сочетании с процедурой завершения или ожиданием перехода дескриптора таймера в сигнальное состояние, что в итоге дает четыре различные комбинации.

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

Функция CancelWaitableTimer используется для отмены действия вызванной перед этим функции SetWaitableTimer, но при этом не изменяет сигнальное состояние таймера. Чтобы это сделать, необходимо в очередной раз вызвать функцию SetWaitableTimer.

Пример: использование таймера ожидания

В программе 14.3 демонстрируется применение таймера ожидания для генерации периодических сигналов.

Программа 14.3. TimeBeep: генерация периодических сигналов

/* Глава 14. TimeBeep.с. Периодическое звуковое оповещение. */

/* Использование: TimeBeep период (в миллисекундах). */

 

#include "EvryThng.h"

static BOOL WINAPI Handler(DWORD CntrlEvent);

static VOID APIENTRY Beeper(LPVOID, DWORD, DWORD);

volatile static BOOL Exit = FALSE;

HANDLE hTimer;

 

int _tmain(int argc, LPTSTR argv[]) {

DWORD Count = 0, Period;

LARGE_INTEGER DueTime;

/* Перехват нажатия комбинации клавиш <Ctrl-c> для прекращения операции. См. главу 4. */

SetConsoleCtrlHandler(Handler, TRUE);

Period = _ttoi(argv[1]) * 1000;

DueTime.QuadPart = –(LONGLONG)Period * 10000;

/* Параметр DueTime отрицателен для первого периода ожидания и задается относительно текущего времени. Период ожидания измеряется в мс (10-3 с), a DueTime — в единицах по 100 нc (10-7 с) для согласования с типом FILETIME. */

hTimer = CreateWaitableTimer(NULL, FALSE /* "Таймер синхронизации" */, NULL);

SetWaitableTimer(hTimer, &DueTime, Period, Beeper, &Count, TRUE);

while (!Exit) {

_tprintf(_T("Count = %d\n"), Count);

/* Значение счетчика увеличивается в процедуре таймера. */

/* Войти в состояние дежурного ожидания. */

SleepEx(INFINITE, TRUE);

}

_tprintf(_T("Завершение. Счетчик = %d"), Count);

CancelWaitableTimer(hTimer);

CloseHandle(hTimer);

return 0;

}

 

static VOID APIENTRY Beeper(LPVOID lpCount, DWORD dwTimerLowValue, DWORD dwTimerHighValue) {

*(LPDWORD)lpCount = *(LPDWORD)lpCount + 1;

_tprintf(_T("Генерация сигнала номер: %d\n"), *(LPDWORD) lpCount);

Веер(1000 /* Частота. */, 250 /* Длительность (мс). */);

return;

}

 

BOOL WINAPI Handler(DWORD CntrlEvent) {

Exit = TRUE;

_tprintf(_T("Завершение работы\n"));

return TRUE;

}





Поделиться с друзьями:


Дата добавления: 2015-09-20; Мы поможем в написании ваших работ!; просмотров: 545 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Что разум человека может постигнуть и во что он может поверить, того он способен достичь © Наполеон Хилл
==> читать все изречения...

2458 - | 2274 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.006 с.