zoukankan      html  css  js  c++  java
  • CreateWaitableTimer 、SetWaitableTimer用于创建无界面的定时器。

    平时创建定时器使用的是WINAPI  SetTimer,不过该函数一般用于有界面的时候。无界面的情况下,可以选择微软提供的CreateWaitableTimer和SetWaitableTimer API。

    HANDLE WINAPI CreateWaitableTimer(
      _In_opt_  LPSECURITY_ATTRIBUTES lpTimerAttributes,
      _In_      BOOL bManualReset,
      _In_opt_  LPCTSTR lpTimerName
    );
    
    BOOL WINAPI SetWaitableTimer(
      _In_      HANDLE hTimer,
      _In_      const LARGE_INTEGER *pDueTime,
      _In_      LONG lPeriod,
      _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
      _In_opt_  LPVOID lpArgToCompletionRoutine,
      _In_      BOOL fResume
    );

    详细介绍可以查看MSDN( http://msdn.microsoft.com/en-us/library/windows/desktop/ms682492(v=vs.85).aspx )

    一、应用实例

    我自己在使用的时候,封装了一个类,用来创建了一个线程,并定时调用我提供的函数。类代码如下:

     1 #ifndef APLAYER_TIMERTHREAD_H
     2 #define APLAYER_TIMERTHREAD_H
     3 #include <Windows.h>
     4 class CTimerThread
     5 {
     6 public:
     7     CTimerThread() :
     8         _hThread(NULL), _hEvent(NULL),
     9         _bRunning(false), _nInterval(10)
    10     {}
    11     ~CTimerThread()
    12     {
    13         KillTimer();
    14     }
    15 public:
    16     int                        CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam);
    17     void                    KillTimer();
    18 private:
    19     static DWORD WINAPI        timerThread(LPVOID lpParam);
    20 
    21 private:
    22     HANDLE                _hTimer;
    23     int                    _nInterval;
    24     HANDLE                _hEvent;
    25     void*                _lpParam;
    26 
    27     PTIMERAPCROUTINE    _callbackFunc;
    28     HANDLE                _hThread;
    29     DWORD                _dwThread;
    30     bool                _bRunning;
    31 };
    32 
    33 #endif
    TimerThread.h
     1 #include "TimerThread.h"
     2 
     3 void CTimerThread::KillTimer()
     4 {
     5     if (_hTimer != NULL) {
     6         CancelWaitableTimer(_hTimer);
     7         CloseHandle(_hTimer);
     8         _hTimer = NULL;
     9     }
    10     _bRunning = false;
    11 }
    12 int CTimerThread::CreateTimer(unsigned int interval, PTIMERAPCROUTINE func, void* lpParam)
    13 {
    14     if (_bRunning) return TRUE;
    15     _nInterval = interval;
    16     _callbackFunc = func;
    17     _lpParam = lpParam;
    18     _bRunning = true;
    19     _hThread = CreateThread(
    20         NULL,
    21         0,
    22         timerThread,
    23         this,
    24         0,
    25         &_dwThread
    26         );
    27     if (_hThread == NULL) {
    28         _bRunning = false;
    29         return FALSE;
    30     }
    31     CloseHandle(_hThread);
    32     return TRUE;
    33 }
    34 
    35 DWORD CTimerThread::timerThread(LPVOID lpParam)
    36 {
    37     CTimerThread* pThis = (CTimerThread*)lpParam;
    38     do {
    39         pThis->_hTimer = CreateWaitableTimer(NULL, FALSE, NULL);
    40         if (pThis->_hTimer == NULL) break;
    41 
    42         LARGE_INTEGER liDueTime;
    43         liDueTime.QuadPart = 0;
    44         BOOL bRet = SetWaitableTimer(
    45             pThis->_hTimer,
    46             &liDueTime,
    47             pThis->_nInterval,
    48             pThis->_callbackFunc,
    49             pThis->_lpParam,
    50             FALSE);
    51         do {
    52             SleepEx(30000, TRUE);
    53         } while (pThis->_bRunning);
    54         return bRet;
    55     } while (0);
    56     return 0;
    57 }
    TimerThread.cpp

    TimerThread.h/cpp实现了一个可以定时调用函数的类。使用的时候也很简单。首先定义一个要被调用的函数

    void __stdcall DoSomething(void *lpParam, DWORD, DWORD)
    {
      //to do
    }
    void *lpParam;
    CTimerThread _timer;
    _timer.CreateTimer(50, DoSomething, lpParam);
    //
    some code
    ....
    //
    _timer.KillTimer();

    DoSomething函数在_timer.CreateTimer 和_timer.KillTimer之间会每隔50ms调用一次。

    二、详细说明

    下面根据我自己的理解介绍下这两个函数。

    1.CreateWaitableTimer

    1 HANDLE WINAPI CreateWaitableTimer(
    2   _In_opt_  LPSECURITY_ATTRIBUTES lpTimerAttributes,
    3   _In_      BOOL bManualReset,
    4   _In_opt_  LPCTSTR lpTimerName
    5 );


    用来创建一个timer对象。首先翻译下MSDN对各参数的介绍(个人理解):

    lpTimerAttributes 

     略过,具体可以查看MSDN或《Windows核心编程》,一般设置为NULL。

    bManualReset  

    If this parameter is TRUE, the timer is a manual-reset notification timer. Otherwise, the timer is a synchronization timer.

    (此处不知道如何翻译才能清晰的传达意思,故抄录原文。用我的语言解释就是,如果为TRUE,则该timer到时间时,需要手动重置才能有下一次;FALSE则每次到时后自动进行下一次计时)

    lpTimerName 

    该timer对象的名称。最大MAX_PATH个字母,区分大小写。

    传递NULL则创建一个没有名字的timer对象。

    如果名称和现有的event,semaphore,mutex,job or file-mapping对象名称冲突,则该函数失败,调用GetLastError会返回ERROR_INVALID_HANDLE错误。原因是这些对象共享相同的命名空间。

    返回值(return value)

    如果函数调用成功,则返回指向timer对象的handle。如果和现有的已命名timer同名,则返回指向该timer的handle。

    2.SetWaitableTimer

    1 BOOL WINAPI SetWaitableTimer(
    2   _In_      HANDLE hTimer,
    3   _In_      const LARGE_INTEGER *pDueTime,
    4   _In_      LONG lPeriod,
    5   _In_opt_  PTIMERAPCROUTINE pfnCompletionRoutine,
    6   _In_opt_  LPVOID lpArgToCompletionRoutine,
    7   _In_      BOOL fResume
    8 );

    启动timer对象。首先翻译下MSDN对各参数的介绍(个人理解):

    hTimer

    指向timer对象的handle。显然可以是CreateWaitableTimer函数返回的handle。

    pDueTime

    该时间之后的timer会signaled(意会下..),间隔为100纳秒(应该就是此值的单位吧?)

    正值的话,就是基于UTC的绝对时间。负值的话就是相对现在的时间了。

    例如-10 000 000表示1s后。

    lPeriod

    嗯,这个就是我比较关心的参数,signaled间隔。类似于SetTimer里那个间隔。单位毫秒(ms)

    为0则只signaled一次。

    pfnCompletionRoutine


    每次signaled都会调用此处的函数了,传递一个函数指针。原型为:

    typedef
    VOID
    (APIENTRY *PTIMERAPCROUTINE)(
        _In_opt_ LPVOID lpArgToCompletionRoutine,  \SetWaitableTimer传入的参数lpArgToCompletionRoutine
        _In_     DWORD dwTimerLowValue,
        _In_     DWORD dwTimerHighValue
        );

    lpArgToCompletionRoutine

    传入的参数,往上看:-)

    fResume

    懒得介绍,自己看msdn,一般设置为FALSE。

    返回值(return value)

    成功返回非零值。

  • 相关阅读:
    闲谈随笔以及对自己的心里暗示
    java利用Scanner获取键盘输入
    【积累】发送验证码按钮倒计时js
    【积累】validate验证框架的使用
    重写toString()方法来描述一个类
    【java基础】 合并两个类型相同的list
    java单例类/
    基本类型的包装类
    强转
    【java基础】面向对象的三大特征---多态
  • 原文地址:https://www.cnblogs.com/zihuyishi/p/3540050.html
Copyright © 2011-2022 走看看