Windows для профессионалов


Ожидаемые таймеры и АРС-очередь - часть 2


Код, приведенный ниже, демонстрирует, как принять эту информацию и показать ее поль зователю.

VOID APIENTRY TimerAPCRoutine(PVOID pvArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwT:merHighValue)
{

FILETIME ftUTC, ftLocal;
SYSTEMTIME st;
TCHAR szBuf[256];

// записываем время в структуру
FILETIME ftUTC.dwlowDateTime = dwTimerLowValue;
ftUTC.dwHighDateFime = dwTimerHighValue;

// преобразуем UTC-время в местное
FileTimeToLocalFileTime(&ftUTC, &ftLocal);

// преобразуем структуру FILETIME в структуру SYSTEMTIME,
// как того требуют функции GetDateFormat и GetTimeFormat
FileTimetoSystemTime(&ftLocal, &st);

// формируем строку с датой и временем, в которой
// сработал таймер
GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szBuf, sizeof(szBuf) / sizeof(TCHAR));
_tcscat(szBuf, __TEXT(' '));
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &st, NULL, _tcschr(szBuf, 0), si/eof(szBuf) / sizeor(TCHAR) - _tcslen(sz8uf));

// показываем время пользователю
MessageBox(NULL, szBuf, "Timer went off at ... ", MB_OK); }

Функция "тревожного ожидания" возвращает управление только после обработ ки вссх элементов АРС-очереди. Поэтому Вы должны позаботиться о том, чтобы Ваша функция TimerAPCRoutine заканчивала свою работу до того, как таймер вновь подаeт сигнал (перейдет в свободное состояние). Иначе говоря, элементы не должны ставить ся в АРС-очередь быстрее, чем они могут быть обработаны.

Следующий фрагмент кода показывает, как правильно пользоваться таймерами и APC:

void SomeFunc() {

//создаем таймер (его тип не имеет значения)
HANDLE hTimer = CreateWaitableTimer(NULL, TRUE, NULL);

// настраиваем таймер на срабатывание через 5 секунд
LARGE_INTEGER li = { 0 };

SetWaitableTimer(hTimer, &li, 5000, TimerAPCRoutine, NULL, FALSE);
// ждем срабатывания таймура в "тревожном" состоянии
SleepEx(INFINITE, TRUE);

CloseHandle(hTimer);
}

И последнее. Взгляните ни эют фрагмент кода:

HANDLE hTimer - CreateWaitableTimer(NULL, FAISE, NULL);
SetWaitableTimer(hTimer, ..., TimerAPCRoutine, );
WaitForSingleObjectEx(hTimer, INFINITE, TRUE);

Никогда ие пнигите такой код, потому что вызов WaitForSingleObjectEx на деле за ставляет дважды ожидать таймер — по описателю hTimer и в "тревожном" состоянии Когда таймер перейдет в свободное состояние, поток пробудится, что выведет eго из "тревожного" состояния, и вызова АРС-функции не последует. Правда, АРС-функции редко используются совместно с ожидаемыми таймерами, так как всегда можно дож даться перехода таймера в свободное состояние, а затем сделать то, что нужно.




Начало  Назад  Вперед



Книжный магазин