1. 程式人生 > >Windows定時器學習

Windows定時器學習

內核對象 arm 三個參數 inf ont 多少 defined win int

定時器是一個在特定時間或者規則間隔被激發的內核對象。結合定時器的異步程序調用可以允許回調函數在任何定時器被激發的時候執行。

通過調用CreateWaitableTimer()可以創建一個定時器,此函數返回一個指向內核對象的句柄。若定時器已經存在,你可以通過使用OpenWaitableTimer()獲得一個進程相關的句柄。無論是通過CreateWaitableTimer() 還是通過OpenWaitableTimer()獲得的句柄,在不需要定時器時必須釋放,方法是使用函數CloseHandle()。

定時的時間通過調用SetWaitableTimer()來設置,可以設置為一個特定的時刻(如December 16, 1999 at 9:45 PM)或者一個相對的時間(如從現在起每五分鐘)。函數SetWaitableTime()定時的時間參數要求LARGE_INTEGER類型。這個值應該符合在結構體FILETIME中描述的格式。如果值是正的,代表一個特定的時刻。如果值是負的,代表以100納秒為單位的相對時間。你也可以將定時器設置為周期性的自我激發,方法是向SetWaitableTimer()的第三個參數傳遞一個周期參數(以毫秒為單位)。在CreateWaitableTimer()的第二個參數傳遞FALSE可以產生一個自動歸零的定時器。

在所有的APC中,要執行一個完全例程則線程必須處於監聽狀態。完全例程將總是被調用SetWaitableTimer()的相同的線程執行,所以此線程必須將必須其自身置於監聽狀態。可以調用下面的任何一個監聽函數來完成監聽狀態的設置:
SleepEx();
WaitForSingleObjectEx();
WaitForMultipleObjectsEx();
MsgWaitForMultipleObjectsEx();
SignalObjectAndWait();

CreateWaitableTimer()函數用於創建一個可等待定時器:

函數原型
HANDLE WINAPI CreateWaitableTimer(
LPSECURITY_ATTRIBUTES lpTimerAttributes,
BOOL bManualReset,
LPCTSTR lpTimerName);

說明
lpSemaphoreAttributes
SECURITY_ATTRIBUTES,指定一個結構,用於設置對象的安全特性。如將參數聲明為ByVal As Long,並傳遞零值,就可使用對象的默認安全設置。
bManualReset
Long,如果為TRUE,表示創建一個人工重置計時器;如果為FALSE,則創建一個自動重置計時器。
lpName
String,指定可等待計時器對象的名稱。用vbNullString可創建一個未命名的計時器對象。如果已經存在擁有這個名字的一個可等待計時器,就直接打開現成的可等待計時器。這個名字可能不與一個現有的互斥體、事件、信號機或文件映射的名稱相符。

函數OpenWaitableTimer()用於得到一個已經存在的可等待計時器的句柄,該句柄與當前進程相關聯:

HANDLE OpenWaitableTimer(  
                    DWORD dwDesiredAccess, /* 訪問權限 */  
                    BOOL bInheritHandle, /* 是否允許子進程繼承該句柄 */  
                    LPCTSTR lpTimerName /* 要打開的對象名稱 */  
); 

在創建的時候,可等待的計時器對象總是處於未觸發狀態。當我們想要觸發計時器時,必須調用SetWaitableTimer()函數:

BOOL SetWaitableTimer(  
                      HANDLE hTimer, /* 想要觸發的計時器 */  
                      const LARGE_INTEGER *pDueTime, /* 計時器第一次觸發的時間 */  
                      LONG lPeriod, /* 第一次觸發後,計時器的觸發頻度 */  
                      PTIMERAPCROUTINE pfnCompletionRoutine, /* 異步過程調用APC函數 */  
                      LPVOID lpArgToCompletionRoutine, /* APC函數的參數 */  
                      BOOL fResume /* 是否繼續執行,一般傳FALSE */  
);

註意,第2個參數pDutTime和第3個參數lPeriod要聯合使用,pDutTime是一個LAGRE_INTEGER結構指針,指明了第一次通知的時間,時間格式是UTC(標準時間),是一個絕對值,如果要設置一個相對值,即讓等待定時器在調用SetWaitableTimer函數之後多少時間發出第一次通知,只要傳遞一個負數給該參數即可,但是該數值必須是100ns的倍數,即單位是100ns。第3個參數指明了以後通知的時間間隔,以毫秒為單位,該參數為0時,表示只有第一次的通知,以後沒有通知。

函數CancelWaitableTimer用來將指定的計時器取消:
BOOL WINAPI CancelWaitableTimer(HANDLE hTimer);

註意,以上提到的幾個函數需要包含<windows.h>頭文件,但是只包含此頭文件編譯會提示:
‘CreateWaitableTimer‘ undefined; assuming extern returning int
需要在包含頭文件之前定義#define _WIN32_WINNT 0x0400,這樣就可以解決CreateWaitableTimer()找不到的問題了。

以下是我寫的一個簡單的例子:

#define _WIN32_WINNT 0x0400  
#include <stdio.h>  
#include <windows.h>  

#define _SECOND 10000000  

void CALLBACK OnTimer(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue)  
{  
    printf("alarm!\n");  
}  

int main()  
{  
    int i;  
    int iRet;  
    LARGE_INTEGER li;  
    HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);  
    if(hTimer == NULL)  
        return -1;  
    li.QuadPart = -2 * _SECOND;  
    iRet = SetWaitableTimer(hTimer, &li, 1000, OnTimer, NULL, FALSE);  
    if(iRet == 0)  
        return -1;  
    for(i = 0; i < 10; i++)  
    {  
        SleepEx(INFINITE, TRUE);  
    }
    system( "PAUSE "); 
    return 0;  
}

轉自http://blog.csdn.net/nevasun/article/details/7282421

Windows定時器學習