这节主要介绍,当触发时间到达时自动触发该触发计时器对象;下一节,将介绍触发时间到达时自动触发该触发计时器对象,同时会把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;
}