Таймер за изчакване
Чакащи таймери
Чакащите таймери са обекти на ядрото, предназначени да отброяват периоди от време. Краят на интервала от време се определя от прехода на таймера в свободно състояние (сигнализира се). Моментът на преминаване на таймера в неактивно състояние се определя от една от чакащите функции. По аналогия с радиоелектрониката, таймерът за изчакване може да бъде представен като мултивибратор, работещ в един от двата режима, чакащ да бъде задействан от външен сигнал или осцилатор, когато се формира непрекъсната последователност от импулси. Основното използване на таймерите за изчакване е синхронизацията на нишки в многонишковото програмиране.
Най-честото използване на чакащите таймери е периодичното изпълнение на конкретна задача. Например е необходимо да се събират данни и да се обработват с определен период. Нито източникът на данните, нито тяхната обработка са важни, основното в задачата е честотата на събиране.
Има няколко функции за създаване и управление на чакащи таймери:
- HANDLE CreateWaitableTimer (LPSECURITY_ATTRIBUTES lpTimerAttributes, BOOL bManualReset, LPCTSTR lpTimerName) - функцията създава таймер за изчакване в заето състояние, от което е изтласкана, т.е. след създаването обектът не е активен. Таймерът може да бъде от два вида с автоматично нулиране или ръчно нулиране, определени от параметъра bManualReset. Ако таймерът се рестартира ръчно, тогава когато преминава в свободно състояние, всички нишки, които са го чакали, се стартират. Таймерът за автоматично нулиране стартира само една нишка. Първият параметър обикновено винаги е NULL, последният е името на таймера. Името се използва за споделяне на обект между процеси.
- BOOL SetWaitableTimer (HANDLE hTimer, const LARGE_INTEGER * pDueTime, LONG lPeriod, PTIMERAPCROUTINE pfnCompletionRoutine,
PVOID pvArgToCompletionRoutine, BOOL bResume) - функцията стартира таймера и определя всички негови параметри. Функцията може да бъде извикана по всяко време за нулиране на таймера, ако в този момент таймерът е бил зает, тогава извикването на функцията не го освобождава; след извикването на функцията таймерът ще продължи да работи с нови параметри. След извикване на функцията таймерът преминава в заето състояние и изтича времето, посочено във втория параметър.
- Първият параметър е дескриптор на таймера.
- Втори параметър pDueTime определя времето за преминаване на таймера в свободно състояние (сигнализирано) или времето на таймера. През това време нишката, която чака изтичането на таймера, е неактивна. Ако е посочена функция за асинхронно повикване (APC), тя се поставя на опашка в момента на изтичане на таймера. Параметър pDueTime може да се определи като абсолютно или относително време, абсолютното време определя момента на първото стартиране и е положителна стойност. Определянето на абсолютно време изисква подготвителни операции за преобразуване на пълна дата в стойност от тип LARGE_INTEGER. Относителното време определя момента на активиране на първия таймер след извикването на функцията. Относителното време е отрицателна стойност, изразена в интервали от 100 ns.
- Трети параметър lПериод определя режима на работа и в същото време периода на повторение на чакащия таймер. Ако периодът е нула, таймерът ще работи веднъж, ако не е нула, действията ще се повторят с посочения период. Стойността се посочва в милисекунди. Трябва да се отбележи, че инсталацията lПериод точно с точност до 1 ms не означава, че на нишката ще бъдат разпределени ресурсите на процесора в точното време. Всъщност периодът на таймера за сърдечен ритъм е приблизително кратен на периода от време, предоставен на нишката от системата. Например на моя компютър системното време, разпределено за нишка, е 15,625 ms. Ако зададете периода на таймера на 20 ms, той действително ще се задейства с период от приблизително 32 ms.
- Четвърти параметър pfnCompletionRoutine дефинира указател към незадължителна функция за асинхронно повикване (APC), която се поставя в опашката на функциите на APC в момента на изтичане на таймера и след това се извиква. Извикването му се извършва от нишката, която е извикала функцията SetWaitableTimer, но при условие, че е в състояние на изчакване, т.е. нишката трябва да извиква и да се намира във функцията за изчакване. Ако нишката не е в чакаща функция, тогава функцията за асинхронно повикване няма да бъде поставена на опашка. Това предпазва от препълване на APC опашката с таймерни повиквания. Функцията за асинхронно повикване трябва да завърши, преди да изтече следващият таймер. Ако се извика функцията APC SetWaitableTimer с нови параметри, функцията APC се изпълнява незабавно и след това вече се изпълнява за новите параметри.
- Петият параметър предава произволен аргумент на функцията за асинхронно повикване (APC), като указател към обект или структура.
- Последен параметър b Резюме, ако не е нула, събужда колата от състояние на заспиване, когато таймерът изтече.