内核对象之可等待对象

(一)分类:

  (一)当到达某一个时间后,才继续线程的执行。

  (二)当到达某一个时间后,调用某一个函数,而且间隔多少时间后,再次调用。

(二)针对第一种情况的步骤:

    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、自动重置计时器,在使用完内核对象后,自动将计时器置为未触发状态。并且该计时器一旦触发,只能随机引起一个线程的调度。

posted @ 2013-09-25 11:17  Fly Hawk  阅读(378)  评论(0编辑  收藏  举报