內核對象--可等待計時器WaitableTimer(一)

這節主要介紹,當觸發時間到達時自動觸發該觸發計時器對象;下一節,將介紹觸發時間到達時自動觸發該觸發計時器對象,同時會把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);


下面我們設置可等待計時器的觸發時間爲2014/1/25 21:02:00,間隔時間5秒鐘
// 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;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章