這節主要介紹,當觸發時間到達時自動觸發該觸發計時器對象;下一節,將介紹觸發時間到達時自動觸發該觸發計時器對象,同時會把APC(異步過程調用)添加進線程的APC隊列中,並執行它。
可等待計時器內核對象:它會在某個指定的時間觸發,或每隔一段時間觸發一次。
使用步驟:
1、創建內核對象
HANDLE CreateWaitableTimer(PSECURITY_ATTRIBUTES psa, BOOL bManualReset, PCTSTR pszName);
2、設置觸發計時器的觸發條件
如果想要觸發計時器,必須調用SetWaitableTimer函數。
BOOL SetWaitableTimer(
HANDLE hTimer,
const LARGE_INTEGER *pDueTime, //設置第一次觸發的時間; 值全爲0,則立即觸發計時器
LONG lPeriod, //觸發後,間隔多長時間再觸發;設爲0,則只觸發一次
PTIMERAPCROUTINE pfnCompletionRoutine,
PVOID pvArgToCompletionRoutine,
BOOL bResume
);
pfnCompletionRoutine和pvArgToCompletionRoutine參數設置爲NULL時,時間一到會觸發計時器對象;
pfnCompletionRoutine和pvArgToCompletionRoutine參數設置不爲NULL時,時間一到會觸發計時器對象,並會讓計時器對象將一個APC添加到線程的APC隊列中;
3、等待計時器觸發
計時器的觸發條件設置成功後,就可以通過下面的函數來等待計時器觸發
DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE *lpHandles, BOOL bWaitAll, DWORD dwMilliseconds);
4、不再需要觸發時間時,可以使用下面的函數來取消觸發時間
BOOL CancelWaitableTimer(HANDLE hTimer);
// WaitableTimer.cpp : 定義控制檯應用程序的入口點。
//
#include "stdafx.h"
#include <Windows.h>
HANDLE g_hTimer = NULL;
HANDLE g_hThread= NULL;
DWORD g_dwThreadID = 0;
SYSTEMTIME g_stime;
DWORD ThreadHander(LPVOID lpThreadParameter);
int _tmain(int argc, _TCHAR* argv[])
{
//Create Thread
g_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ThreadHander, NULL, CREATE_SUSPENDED, &g_dwThreadID);
if(g_hThread == NULL) {
printf("CreateThread() is fails!\n");
}
else {
printf("CreateThread() is succesful!\n");
printf("Thread:%p, ThreadID:%d\n", g_hThread, g_dwThreadID);
}
//啓動線程
ResumeThread(g_hThread);
//Create Waitable Timer
g_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
if(g_hTimer == NULL) {
printf("CreateWaitableTimer() is successful!\n");
}
Sleep(0);
//設置定時器2014/1/25 21:02:00啓動時間, 啓動以後再間隔5秒啓動一次
SYSTEMTIME st;
FILETIME ftLocal, ftUTC;
LARGE_INTEGER liUTC;
st.wYear = 2014;
st.wMonth= 1;
st.wDayOfWeek = 0;
st.wDay = 25;
st.wHour= 21;
st.wMinute = 2;
st.wSecond = 0;
st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ftLocal);
//轉換本地時間到UTC時間
LocalFileTimeToFileTime(&ftLocal, &ftUTC);
//轉換FILETIME到LARGE_INTEGER
liUTC.LowPart = ftUTC.dwLowDateTime;
liUTC.HighPart= ftUTC.dwHighDateTime;
//liUTC.QuadPart= -5*10000000; //設置函數調用後5秒鐘開始執行
GetLocalTime(&g_stime);
printf("開始時間:%02d:%02d:%02d %03d\n", g_stime.wHour, g_stime.wMinute, g_stime.wSecond, g_stime.wMilliseconds);
if (FALSE != SetWaitableTimer(g_hTimer,&liUTC, 5*1000, NULL, NULL, FALSE) ) {
printf("SetWaitableTimer() return TRUE!\n");
}
int n=1;
while(true) {
Sleep(1000);
//printf("main() %d\n", n++);
}
system("pause");
return 0;
}
DWORD ThreadHander(LPVOID lpThreadParameter)
{
int n=1;
while(true) {
switch(WaitForSingleObject(g_hTimer, INFINITE))
{
case WAIT_OBJECT_0:
GetLocalTime(&g_stime);
printf(">> 時間:%02d:%02d:%02d %03d\n", g_stime.wHour, g_stime.wMinute, g_stime.wSecond, g_stime.wMilliseconds);
break;
case WAIT_TIMEOUT:
printf("WaitForSingleObject(): WAIT_TIMEOUT\n");
break;
default:
printf("WaitForSingleObject(): 錯誤%d\n", GetLastError());
break;
}
}
printf("線程退出:%d\n", n++);
return 0;
}