小步慢跑

 

基于 TimerQueue 的定时器封装类

本来以为是很简单的事,没想到又牵涉出了线程池,APC,内核定时器对象一大堆没搞明白的知识。先把代码保存下。牵涉到的知识再慢慢消化。

主要使用了以下 API。这些API还是有不少的陷阱(注意点)的,《windows 核心编程》的第11章有详细的解释。

   1: CreateTimerQueue
   2: DeleteTimerQueueEx
   3:  
   4: CreateTimerQueueTimer
   5: DeleteTimerQueueTimer

h文件

   1: #pragma once
   2:  
   3:  
   4: /*
   5:  *    无窗口的定时器方案
   6:  */
   7:  
   8: #include "singleton.h" 
   9:  
  10: typedef tr1::function<void(DWORD dwID,DWORD dwUserData)> TimerFunObj;
  11:  
  12: class CTimerMgr
  13: {
  14: public:
  15:     CTimerMgr(void);
  16:     ~CTimerMgr(void);
  17:  
  18:  
  19: public:
  20:     bool SetTimer(DWORD dwID,DWORD dwElapse,TimerFunObj,DWORD dwUserData);
  21:     bool KillTimer(DWORD dwID);
  22:  
  23: private:
  24:  
  25:     typedef map<DWORD ,HANDLE>  MAP_ID_2_HANDLE;
  26:     MAP_ID_2_HANDLE m_mapTimerID2Handle; //定时器id 映射到定时器的handle
  27:  
  28:     HANDLE m_hTimerQueue;
  29: };
  30:  
  31: typedef Singleton<CTimerMgr> TimerService;
  32:  
  33: struct TCBParam
  34: {
  35:     CTimerMgr*  m_pThis;
  36:     DWORD       m_dwTimerID;
  37:     TimerFunObj m_func;
  38:     DWORD       m_dwUserData;
  39: };
  40: extern void _stdcall  TimerCBProc(PVOID lpParamter,BOOL TimerorWaitFired);

 

cpp文件

   1: #include "StdAfx.h"
   2: #include "TimerMgr.h"
   3:  
   4:  
   5: CTimerMgr::CTimerMgr(void):m_hTimerQueue(NULL)
   6: {
   7:     m_hTimerQueue = ::CreateTimerQueue();
   8:     VERIFY(NULL != m_hTimerQueue);
   9: }
  10:  
  11:  
  12: CTimerMgr::~CTimerMgr(void)
  13: {
  14:     if (NULL != m_hTimerQueue)
  15:     {
  16:         // INVALID_HANDLE_VALUE:会导致DeleteTimerQueueEx等待所有的timer对应的回调方法完成后再返回
  17:         DeleteTimerQueueEx(m_hTimerQueue,NULL);
  18:     }
  19: }
  20:  
  21: // dwElapse :milliseconds
  22: bool CTimerMgr::SetTimer( DWORD dwID,DWORD dwElapse,TimerFunObj timerfunc,DWORD dwUserData)
  23: {
  24:     VERIFY(NULL != m_hTimerQueue);
  25:     
  26:     TCBParam* ptParam     = new TCBParam;
  27:     ptParam->m_pThis      = this;
  28:     ptParam->m_dwTimerID  = dwID;
  29:     ptParam->m_func       = timerfunc;
  30:     ptParam->m_dwUserData = dwUserData;
  31:  
  32:     HANDLE hTimer = NULL;
  33:     if( 0 != CreateTimerQueueTimer(&hTimer,m_hTimerQueue,(WAITORTIMERCALLBACK)TimerCBProc,(void*)ptParam,dwElapse,0,WT_EXECUTEDEFAULT))
  34:     {
  35:         m_mapTimerID2Handle[dwID] = hTimer;
  36:         return true;
  37:     }
  38:     else //失败
  39:     {
  40:         delete ptParam;
  41:         ptParam = NULL;
  42:         return false;
  43:     }
  44:  
  45: }
  46:  
  47: bool CTimerMgr::KillTimer( DWORD dwID )
  48: {
  49:     MAP_ID_2_HANDLE::iterator it = m_mapTimerID2Handle.find(dwID);
  50:  
  51:     if (it == m_mapTimerID2Handle.end())//不存在
  52:         return false;
  53:         
  54:     HANDLE hTimer = it->second;
  55:     BOOL bSuc = ( 0 != ::DeleteTimerQueueTimer(m_hTimerQueue,hTimer,NULL) );
  56:  
  57:     if (bSuc )
  58:     {
  59:         m_mapTimerID2Handle.erase(it);
  60:         return true;
  61:     }
  62:     //之前定义的处理函数即将被调用或正在被调用,立刻返回,但系统会在处理函数调用完成后自动删除这个定时器
  63:     else if (ERROR_IO_PENDING ==  GetLastError())
  64:     {
  65:         m_mapTimerID2Handle.erase(it);
  66:         return true;
  67:     }
  68:     else
  69:     {
  70:         return false;
  71:     }
  72:         
  73:         
  74:     
  75:     
  76: }
  77:  
  78:  
  79: void _stdcall TimerCBProc( PVOID lpParamter,BOOL TimerorWaitFired )
  80: {
  81:     TCBParam* ptParam = (TCBParam*)lpParamter;
  82:     if (NULL == ptParam)
  83:         return;
  84:     CTimerMgr*  pThis      = ptParam->m_pThis;
  85:     DWORD       dwTimerID  = ptParam->m_dwTimerID;
  86:     TimerFunObj funcTimer  = ptParam->m_func;
  87:     DWORD       dwUserData = ptParam->m_dwUserData;
  88:  
  89:     funcTimer(dwTimerID,dwUserData);
  90:     
  91:     delete ptParam;
  92:     ptParam = NULL;
  93: }

调用代码:

   1: class CInvoker
   2: {
   3: public:
   4:     void TimerProc(DWORD dwID,DWORD dwUserData )
   5:     {
   6:         //...
   7:     }
   8: }
   9:  
  10: CInvoker _invoker;
  11: TimerFunObj  proc = tr1::bind(&CInvoker::TimerProc,&_invoker,tr1::placeholders::_1,tr1::placeholders::_2);

posted on 2012-08-14 19:09 zaccheo 阅读(938) 评论(0)  编辑 收藏 引用 所属分类: C++ win32/MFC


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


导航

统计

常用链接

留言簿

随笔分类(23)

随笔档案(26)

文章分类(1)

文章档案(1)

csdn

搜索

最新评论

阅读排行榜

评论排行榜