1、常用的方法是SetTimer,但WM_TIMER消息的优先级是低级别的。
这种消息只会在线程的消息队列中没有更高级的消息,才会被处理。
2、使用waitable timer oject
2.1 创建一个 waitable timer
HANDLE CreateWaitableTimer( PSECURITY_ATTRIBUTES psa, BOOL bManualReset, PCTSTR pszName);
bManualReset:用于标识此timer是人工重置的还是自动重置的。
如果是人工重置的Timer,当此timer处于触发状态(signaled)时,所有等待此timer的线程都会变成可调度状态;
如果是自动重置的Timer,当此timer处于触发状态(signaled)时,所有等待此timer的线程中只要一个线程变成可调度状态。
2.2 打开一个已存在的waitable timer
HANDLE OpenWaitableTimer( PSECURITY_ATTRIBUTES psa, BOOL bInheritHandle, PCTSTR pszName);
2.3 设置waitable timer,waitable timer在创建后是处于非触发状态的(nonsignaled)。
BOOL SetWaitableTimer( HANDLE hTimer,
const LARGE_INTEGER *pDueTime,
LONG lPeriod,
PTIMERAPCROUTINE pfnCompletionRoutine,
PVOID pvArgToCompletionRoutine,
BOOL bResume);
pDueTime: 用于指定第一次触发Timer的时间。
lPeriod:用于指定第一次触发之后,再次被触发的时间间隔。
pfnCompletionRoutine:timer被触发后的回调函数(可选的)。
执行回调函数的线程和执行SetWaitableTimer函数的线程是同一个。
回调函数的原型为:
VOID APIENTRY TimerAPCRoutine(PVOID pvArgToCompletionRoutine,
DWORD dwTimerLowValue,
DWORD dwTimerHighValue);
注:执行SetWaitableTimer函数的线程必须是处于可alertable状态,否则回调函数不会被执行。
执行下面的函数函数可使处于可alertable状态:
SleepEx,WitForSingleObjectEx, WaitForMultipleObjectsEx, MsgWaitForMultipleObjectsEx, SignalObjectAndWait
2.4 注销waitable timer
BOOL CancelWaitableTimer( HANDLE hTimer );
2.5 注意
不要在同一个线程中即等待timer的句柄,又等待timer所在的线程处于可alertable状态。例如:
HANDLE hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
SetWaitableTimer(hTimer, ..., TimerAPCRoutine,...);
WaitForSingleObjectEx(hTimer, INFINITE, TRUE);
当timer变成触发状态时,WaitForSingleObjectEx函数返回,并且线程从可alertable状态变成苏醒状态。
因此造成TimerAPCRoutine不会被执行。
3、使用Thread pool Timer
3.1 创建Thread pool Timer
PTP_TIMER CreateThreadpoolTimer( PTP_TIMER_CALLBACK pfnTimerCallback,
PVOID pvContext,
PTP_CALLBACK_ENVIRON pcbe);
pfnTimerCallback:回调函数。函数原型为:
VOID CALLBACK TimeoutCallback(PTP_CALLBACK_INSTANCE pInstance,
PVOID pvContext,
P_TIMER pTimer);
3.2 设置Thread pool Timer
VOID SetThreadpoolTimer(PTP_TIMER pTimer,
PFILETIME pftDueTime,
DWORD msPeriod,
DWORD msWindowLength);
3.3 注销Thread pool Timer
VOID CloseThreadpoolTimer(PTP_TIMER pTimer);