АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция
|
Ожидаемые таймеры
Пожалуй, ожидаемые таймеры - самый изощренный объект ядра для синхронизации. Появились они, начиная с Windows 98. Таймеры создаются функцией CreateWaitableTimer и бывают, также как и события, с автосбросом и без него. Затем таймер надо настроить функцией SetWaitableTimer. Таймер переходит в сигнальное состояние, когда истекает его таймаут. Отменить "тиканье" таймера можно функцией CancelWaitableTimer. Примечательно, что можно указать callback функцию при установке таймера. Она будет выполняться, когда срабатывает таймер.
| Пример 8. Напишем программу-будильник используя WaitableTimer'ы. Будильник будет срабатыват раз в день в 8 утра и "пикать" 10 раз. Используем для этого два таймера, один из которых с callback-функцией.
|
| #include <process.h> #include <windows.h> #include <stdio.h> #include <conio.h> #define HOUR (8) // время, когда срабатывает будильник (только часы) #define RINGS (10) // сколько раз пикать HANDLE hTerminateEvent; // callback функция таймера VOID CALLBACK TimerAPCProc(LPVOID, DWORD, DWORD) { Beep(1000,500); // звоним! }; // функция потока unsigned __stdcall ThreadFunc(void *) { HANDLE hDayTimer = CreateWaitableTimer(NULL,FALSE,NULL); HANDLE hAlarmTimer = CreateWaitableTimer(NULL,FALSE,NULL); HANDLE h[2]; // мы будем ждать эти объекты h[0] = hTerminateEvent; h[1] = hDayTimer; int iRingCount=0; // число "звонков" int iFlag; DWORD dw; // немного помучаемся со временем, //т.к. таймер принимает его только в формате FILETIME LARGE_INTEGER liDueTime, liAllDay; liDueTime.QuadPart=0; // сутки в 100-наносекундных интервалах = 10000000 * 60 * 60 * 24 = 0xC92A69C000 liAllDay.QuadPart = 0xC9; liAllDay.QuadPart=liAllDay.QuadPart << 32; liAllDay.QuadPart |= 0x2A69C000; SYSTEMTIME st; GetLocalTime(&st); // узнаем текущую дату/время iFlag = st.wHour > HOUR; // если назначенный час еще не наступил, //то ставим будильник на сегодня, иначе - на завтра st.wHour = HOUR; st.wMinute = 0; st.wSecond =0; FILETIME ft; SystemTimeToFileTime(&st, &ft); if (iFlag) ((LARGE_INTEGER *)&ft)->QuadPart = ((LARGE_INTEGER *)&ft)->QuadPart +liAllDay.QuadPart; LocalFileTimeToFileTime(&ft,&ft); // Устанавливаем таймер, // он будет срабатывать раз в сутки (24*60*60*1000ms), // начиная со следующего "часа пик" - HOUR SetWaitableTimer(hDayTimer, (LARGE_INTEGER *) &ft, 24*60*60000, 0, 0, 0); do { dw = WaitForMultipleObjectsEx(2,h,FALSE,INFINITE,TRUE); if (dw == WAIT_OBJECT_0 +1) // сработал hDayTimer { // Устанавливаем таймер, он будет вызывать callback ф-ию раз в секунду, // начнет с текущего момента SetWaitableTimer(hAlarmTimer, &liDueTime, 1000, TimerAPCProc, NULL, 0); iRingCount=0; } if (dw == WAIT_IO_COMPLETION) // закончила работать callback ф-ия { iRingCount++; if (iRingCount==RINGS) CancelWaitableTimer(hAlarmTimer); } }while (dw!= WAIT_OBJECT_0); // пока не сработало hTerminateEvent крутимся в цикле // закрывае handles, выходим CancelWaitableTimer(hDayTimer); CancelWaitableTimer(hAlarmTimer); CloseHandle(hDayTimer); CloseHandle(hAlarmTimer); _endthreadex(0); return 0; }; int main(int argc, char* argv[]) { // это событие показывае потоку когда надо завершаться hTerminateEvent = CreateEvent(NULL,FALSE,FALSE,NULL); unsigned uThreadID; HANDLE hThread; // создаем поток hThread = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, 0, 0,&uThreadID); puts("Press any key to exit."); // ждем any key от пользователя для завершения программы getch(); // выставляем событие SetEvent(hTerminateEvent); // ждем завершения потока WaitForSingleObject(hThread, INFINITE); // закрываем handle CloseHandle(hThread); return 0; } |
1 | 2 | 3 | 4 | 5 | 6 | Поиск по сайту:
|