(一)分类:
(一)当到达某一个时间后,才继续线程的执行。
(二)当到达某一个时间后,调用某一个函数,而且间隔多少时间后,再次调用。
(二)针对第一种情况的步骤:
1、CreateWaitableTimer,创建可等待的内核对象
2、SetWaitableTimer,设置间隔时间、启动时间、APC(asynchronous procedure call)函数、APC参数、是否可以唤醒电脑。
3、WaitForSingleObject,等待时间到了,触发对象。
4、然后接着执行你的操作
对第一种情况的理解:
当执行到某一种时间,才让这个线程继续执行。
代码:
#include <iostream>
#include <ctime>
#include <afxwin.h>
using namespace std;
HANDLE g_hWaitTimer;
void main()
{
//创建一个可等待的计时器
g_hWaitTimer = CreateWaitableTimer(NULL, FALSE, NULL);
//设定一个时间,并将该时间转换成全球标准时间
SYSTEMTIME st;
FILETIME ftLocal, ftUTC;
LARGE_INTEGER liUTC;
st.wYear = 2013;
st.wMonth = 9;
st.wDay = 25;
st.wDayOfWeek = 0;
st.wHour = 10;
st.wMinute = 57;
st.wSecond = 0;
st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ftLocal);
LocalFileTimeToFileTime(&ftLocal, &ftUTC);
liUTC.LowPart = ftUTC.dwLowDateTime;
liUTC.HighPart = ftUTC.dwHighDateTime;
SetWaitableTimer(g_hWaitTimer, &liUTC, 1000, NULL, NULL, FALSE);
for (int i = 0; i < 5; i++)
{
WaitForSingleObject(g_hWaitTimer, INFINITE);
time_t t = time(NULL);
char tmp[64];
strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A",localtime(&t) );
cout <<"The Time is : "<< tmp << endl;
}
CancelWaitableTimer(g_hWaitTimer);
CloseHandle(g_hWaitTimer);
}
结果:
注意:
一定要使用WaitForSingleObject这类函数使对象触发。
(三)针对第二种情况的步骤:
1、CreateWaitableTimer,创建可等待的内核对象
2、SetWaitableTimer,设置间隔时间、启动时间、APC(asynchronous procedure call)函数、APC参数、是否可以唤醒电脑。
3、Sleep,让调用的线程睡眠。
对第二种情况的理解:
当执行到某一种时间,执行APC函数,然后再返回到线程来执行,在此期间保持调用线程处于休眠状态。
代码:
#include <iostream>
#include <ctime>
#include <afxwin.h>
using namespace std;
HANDLE g_hWaitTimer;
VOID CALLBACK TimerAPCProc(
LPVOID lpArgToCompletionRoutine,
DWORD dwTimerLowValue ,
DWORD dwTimerHighValue
)
{
time_t t = time(NULL);
char tmp[64];
strftime( tmp, sizeof(tmp), "%Y/%m/%d %X %A",localtime(&t) );
cout <<"The Time is : "<< tmp << endl;
}
void main()
{
//创建一个可等待的计时器
g_hWaitTimer = CreateWaitableTimer(NULL, FALSE, NULL);
//设定一个时间,并将该时间转换成全球标准时间
SYSTEMTIME st;
FILETIME ftLocal, ftUTC;
LARGE_INTEGER liUTC;
st.wYear = 2013;
st.wMonth = 9;
st.wDay = 25;
st.wDayOfWeek = 0;
st.wHour = 11;
st.wMinute = 10;
st.wSecond = 0;
st.wMilliseconds = 0;
SystemTimeToFileTime(&st, &ftLocal);
LocalFileTimeToFileTime(&ftLocal, &ftUTC);
liUTC.LowPart = ftUTC.dwLowDateTime;
liUTC.HighPart = ftUTC.dwHighDateTime;
SetWaitableTimer(g_hWaitTimer, &liUTC, 1000, TimerAPCProc, NULL, FALSE);
for(int i = 0; i < 5; i++)
{
SleepEx(INFINITE, TRUE);
cout << "Thread is waked...." << endl;
}
CancelWaitableTimer(g_hWaitTimer);
CloseHandle(g_hWaitTimer);
}
结果:
(四)其实还可以设置一个相对时间,相对于SetWaitableTimer这个函数的执行时间。注意这个相间是针对100纳秒的。并且要将这个值设为负值。
1秒 = 1000毫秒 = 1000000微秒 = 10000000个100纳秒
所以我们可以这样:
LARGE_INTEGER liUTC;
liUTC = -(5 * 10000000);
这就表示当执行完SetWaitableTimer后的5秒开始触发内核对象。
(五)可等待计时器还可以分为手动重置计时器与自动重置计时器。
区别:
1、手动重置计时器,在使用完内核对象后,需要手动将计时器置为未触发状态。并且该计时器一旦触发,将引起多个线程的调度。
2、自动重置计时器,在使用完内核对象后,自动将计时器置为未触发状态。并且该计时器一旦触发,只能随机引起一个线程的调度。