CreateWaitableTimer 、SetWaitableTimer用於創建無界面的定時器。


平時創建定時器使用的是WINAPI  SetTimer,不過該函數一般用於有界面的時候。無界面的情況下,可以選擇微軟提供的CreateWaitableTimer和SetWaitableTimer API。

 

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

BOOL WINAPI SetWaitableTimer(
  _In_      HANDLE hTimer,
  _In_      const LARGE_INTEGER *pDueTime,
  _In_      LONG lPeriod,
  _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
  _In_opt_  LPVOID lpArgToCompletionRoutine,
  _In_      BOOL fResume
);

詳細介紹可以查看MSDN( http://msdn.microsoft.com/en-us/library/windows/desktop/ms682492(v=vs.85).aspx )

一、應用實例

我自己在使用的時候,封裝了一個類,用來創建了一個線程,並定時調用我提供的函數。類代碼如下:

 1 #ifndef APLAYER_TIMERTHREAD_H
 2 #define APLAYER_TIMERTHREAD_H
 3 #include <Windows.h>
 4 class CTimerThread
 5 {
 6 public:
 7     CTimerThread() :
 8         _hThread(NULL), _hEvent(NULL),
 9         _bRunning(false), _nInterval(10)
10     {}
11     ~CTimerThread()
12     {
13         KillTimer();
14     }
15 public:
16     int                        CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam);
17     void                    KillTimer();
18 private:
19     static DWORD WINAPI        timerThread(LPVOID lpParam);
20 
21 private:
22     HANDLE                _hTimer;
23     int                    _nInterval;
24     HANDLE                _hEvent;
25     void*                _lpParam;
26 
27     PTIMERAPCROUTINE    _callbackFunc;
28     HANDLE                _hThread;
29     DWORD                _dwThread;
30     bool                _bRunning;
31 };
32 
33 #endif
TimerThread.h
 1 #include "TimerThread.h"
 2 
 3 void CTimerThread::KillTimer()
 4 {
 5     if (_hTimer != NULL) {
 6         CancelWaitableTimer(_hTimer);
 7         CloseHandle(_hTimer);
 8         _hTimer = NULL;
 9     }
10     _bRunning = false;
11 }
12 int CTimerThread::CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam)
13 {
14     if (_bRunning) return TRUE;
15     _nInterval = interval;
16     _callbackFunc = func;
17     _lpParam = lpParam;
18     _bRunning = true;
19     _hThread = CreateThread(
20         NULL,
21         0,
22         timerThread,
23         this,
24         0,
25         &_dwThread
26         );
27     if (_hThread == NULL) {
28         _bRunning = false;
29         return FALSE;
30     }
31     CloseHandle(_hThread);
32     return TRUE;
33 }
34 
35 DWORD CTimerThread::timerThread(LPVOID lpParam)
36 {
37     CTimerThread* pThis = (CTimerThread*)lpParam;
38     do {
39         pThis->_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
40         if (pThis->_hTimer == NULL) break;
41 
42         LARGE_INTEGER liDueTime;
43         liDueTime.QuadPart = 0;
44         BOOL bRet = SetWaitableTimer(
45             pThis->_hTimer,
46             &liDueTime,
47             pThis->_nInterval,
48             pThis->_callbackFunc,
49             pThis->_lpParam,
50             FALSE);
51         do {
52             SleepEx(30000, TRUE);
53         } while (pThis->_bRunning);
54         return bRet;
55     } while (0);
56     return 0;
57 }
TimerThread.cpp

TimerThread.h/cpp實現了一個可以定時調用函數的類。使用的時候也很簡單。首先定義一個要被調用的函數

void __stdcall DoSomething(void *lpParam, DWORD, DWORD)
{
  //to do
}
void *lpParam;
CTimerThread _timer;
_timer.CreateTimer(50, DoSomething, lpParam);
//
some code
....
//
_timer.KillTimer();

DoSomething函數在_timer.CreateTimer 和_timer.KillTimer之間會每隔50ms調用一次。

二、詳細說明

下面根據我自己的理解介紹下這兩個函數。

1.CreateWaitableTimer

1 HANDLE WINAPI CreateWaitableTimer(
2   _In_opt_  LPSECURITY_ATTRIBUTES lpTimerAttributes,
3   _In_      BOOL bManualReset,
4   _In_opt_  LPCTSTR lpTimerName
5 );


用來創建一個timer對象。首先翻譯下MSDN對各參數的介紹(個人理解):

lpTimerAttributes 

 略過,具體可以查看MSDN或《Windows核心編程》,一般設置為NULL。

bManualReset  

If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer.

(此處不知道如何翻譯才能清晰的傳達意思,故抄錄原文。用我的語言解釋就是,如果為TRUE,則該timer到時間時,需要手動重置才能有下一次;FALSE則每次到時后自動進行下一次計時)

lpTimerName 

該timer對象的名稱。最大MAX_PATH個字母,區分大小寫。

傳遞NULL則創建一個沒有名字的timer對象。

如果名稱和現有的event,semaphore,mutex,job or file-mapping對象名稱沖突,則該函數失敗,調用GetLastError會返回ERROR_INVALID_HANDLE錯誤。原因是這些對象共享相同的命名空間。

返回值(return value)

如果函數調用成功,則返回指向timer對象的handle。如果和現有的已命名timer同名,則返回指向該timer的handle。

2.SetWaitableTimer

1 BOOL WINAPI SetWaitableTimer(
2   _In_      HANDLE hTimer,
3   _In_      const LARGE_INTEGER *pDueTime,
4   _In_      LONG lPeriod,
5   _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
6   _In_opt_  LPVOID lpArgToCompletionRoutine,
7   _In_      BOOL fResume
8 );

啟動timer對象。首先翻譯下MSDN對各參數的介紹(個人理解):

hTimer

指向timer對象的handle。顯然可以是CreateWaitableTimer函數返回的handle。

pDueTime

該時間之后的timer會signaled(意會下..),間隔為100納秒(應該就是此值的單位吧?)

正值的話,就是基於UTC的絕對時間。負值的話就是相對現在的時間了。

例如-10 000 000表示1s后。

lPeriod

嗯,這個就是我比較關心的參數,signaled間隔。類似於SetTimer里那個間隔。單位毫秒(ms)

為0則只signaled一次。

pfnCompletionRoutine


每次signaled都會調用此處的函數了,傳遞一個函數指針。原型為:

typedef
VOID
(APIENTRY *PTIMERAPCROUTINE)(
    _In_opt_ LPVOID lpArgToCompletionRoutine,  \\SetWaitableTimer傳入的參數lpArgToCompletionRoutine
    _In_     DWORD dwTimerLowValue,
    _In_     DWORD dwTimerHighValue
    );

 

lpArgToCompletionRoutine

傳入的參數,往上看:-)

fResume

懶得介紹,自己看msdn,一般設置為FALSE。

返回值(return value)

成功返回非零值。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM