现在的位置: 首页 > 综合 > 正文

超强Timer—— 用于需要对时间精确控制或者消息队列很忙的情况

2013年03月16日 ⁄ 综合 ⁄ 共 3568字 ⁄ 字号 评论关闭

用法和Windows API的timer类似 只不过要用类的实例

如:

SuperTimer st;

st.SetTimer(...........);

st.KillTimer(............);

 

/// high PRI timer
/// in this timer we'd better user less time than the timer interval
class SuperTimer
{
public:
 SuperTimer()
 {
  InitializeCriticalSection(&m_cs);
  InitializeCriticalSection(&m_cssend);
  m_hEventForSendTimer = CreateEvent(NULL, FALSE, FALSE, NULL);
  m_hEventEndThread = CreateEvent(NULL, FALSE, FALSE, NULL);

  uintptr_t tid = _beginthread(DoTimerThread, 0, this);

 }
 ~SuperTimer()
 {
  SetEvent(m_hEventEndThread);

  for(MMIDMAP::iterator pos = m_timerIDMap.begin(); pos != m_timerIDMap.end(); ++pos)
  {
   KillTimer(pos->first.first, pos->first.second);
  }
  CloseHandle(m_hEventEndThread);
  CloseHandle(m_hEventForSendTimer);

  DeleteCriticalSection(&m_cs);
  DeleteCriticalSection(&m_cssend);
 }
 UINT_PTR SetTimer(__in_opt HWND hWnd, __in UINT_PTR nIDEvent, __in UINT uElapse, __in_opt TIMERPROC lpTimerFunc = NULL)
 {
//  CriticalLock clk(m_cskill);
  CriticalLock cl(m_cs);
  UserCallbackData *pucd =  new UserCallbackData(hWnd, nIDEvent, this);

  MMRESULT mmrt = timeSetEvent(uElapse, 200,  (LPTIMECALLBACK)&TimeCallBack, (DWORD_PTR)pucd, TIME_PERIODIC);
 
  if(!mmrt)
   return 0;

  m_timerIDMap[make_pair(hWnd, nIDEvent)] = make_pair(
   mmrt,
   pucd);
  return nIDEvent;

 }
 void KillTimer(__in_opt HWND hWnd, __in UINT_PTR uIDEvent)
 {
  UserCallbackData *pucd = new UserCallbackData(hWnd, uIDEvent, this);

  killTimerThread(pucd);

//  uintptr_t tid = _beginthread(killTimerThread, 0, pucd);

 }

private:

 /// timer callback function
 static void CALLBACK TimeCallBack(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2 )
 {
  UserCallbackData *pucd = (UserCallbackData*)dwUser;
  {
   CriticalLock cl(pucd->psTimer->m_cssend);
   pucd->psTimer->m_qcdataForSendTimer.push(*(UserCallbackData *)dwUser);

  }
  SetEvent(pucd->psTimer->m_hEventForSendTimer);
 }

 /// we kill timer in this function
 static void killTimerThread(void *pdata)
 {
  UserCallbackData *pucd = (UserCallbackData*)pdata;
  CriticalLock cl(pucd->psTimer->m_cs);
  MMIDMAP::iterator pos = pucd->psTimer->m_timerIDMap.find(make_pair(pucd->hWnd, pucd->nIDEvent));

  if(pos != pucd->psTimer->m_timerIDMap.end())
  {
   timeKillEvent(pos->second.first);
   delete pos->second.second;
   pucd->psTimer->m_timerIDMap.erase(pos);
  }
  delete pdata;
 }

 /// we send WM_TIMER messages in this thread
 static void DoTimerThread(void *pdata)
 {
  SuperTimer *pThis = (SuperTimer*)pdata;
  while(true)
  {
   HANDLE hEvents[] = {pThis->m_hEventForSendTimer, pThis->m_hEventEndThread };

   DWORD dwrt = WaitForMultipleObjects(2, hEvents, FALSE, INFINITE);

   switch(dwrt)
   {
   case WAIT_OBJECT_0:
    while(true)
    {
     UserCallbackData ucd;
     {
      CriticalLock cl(pThis->m_cssend);
      if(pThis->m_qcdataForSendTimer.empty())
       break;
      ucd = pThis->m_qcdataForSendTimer.front();
      pThis->m_qcdataForSendTimer.pop();
     }

     //  CriticalLock cl(pucd->sTimer.m_cs);
     SendMessage(ucd.hWnd, WM_TIMER, ucd.nIDEvent, 0);
    }
    break;

   case WAIT_OBJECT_0 + 1:
    _endthread();
    break;

   }
  }
 }

 

 /// information for sending WM_TIMER message
 struct UserCallbackData
 {
  UserCallbackData() : hWnd(NULL), nIDEvent(-1), psTimer(NULL)
  {
  }
  UserCallbackData(HWND hwnd, UINT_PTR nevent, SuperTimer *pstimer) : hWnd(hwnd), nIDEvent(nevent), psTimer(pstimer)
  {
  }
  UserCallbackData(const UserCallbackData &ucd) : hWnd(ucd.hWnd), nIDEvent(ucd.nIDEvent), psTimer(ucd.psTimer)
  {
  }
  HWND hWnd;
  UINT_PTR nIDEvent;
  SuperTimer *psTimer;
 };

 /// timer map to maintain timers
 typedef map<pair<HWND, UINT_PTR>, pair<MMRESULT, UserCallbackData*> > MMIDMAP;
 MMIDMAP m_timerIDMap;

 CRITICAL_SECTION m_cs, m_cssend;
 HANDLE m_hEventForSendTimer;
 HANDLE m_hEventEndThread;

 /// queue for WM_TIMER
 queue<UserCallbackData> m_qcdataForSendTimer;
 
};
 

抱歉!评论已关闭.