• 内核对象之可等待对象


    (一)分类:

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

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

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

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

  • 相关阅读:
    新经资讯项目业务逻辑梳理
    HTTP状态保持的原理
    CSRF的原理和防范措施
    装饰器路由具体实现梳理
    Flask中异常捕获
    正则匹配路由
    (搬运以学习)flask 上下文的实现
    flask之请求钩子
    如何在linux中创建虚拟环境
    面包屑导航
  • 原文地址:https://www.cnblogs.com/wang-can/p/3338347.html
Copyright © 2020-2023  润新知