内核对象之可等待对象
(一)分类:
(一)当到达某一个时间后,才继续线程的执行。
(二)当到达某一个时间后,调用某一个函数,而且间隔多少时间后,再次调用。
(二)针对第一种情况的步骤:
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、自动重置计时器,在使用完内核对象后,自动将计时器置为未触发状态。并且该计时器一旦触发,只能随机引起一个线程的调度。