目前,我的掌握的windows定時器有三種方式(使用vs08測試,都可在控制檯下實現):windows
1.使用線程方式與waitforsingleobject結合;函數
2.使用SetTimer;測試
3.使用多媒體定時器;this
代碼以下:spa
SetTimer定時器封裝以下:線程
#pragma once #include "vos/vos.h" #define _WIN32_WINNT 0x0400 #include <atltime.h> #include <windows.h> class CWin32Timer { public: CWin32Timer(TIMERPROC fun, unsigned int interval = 1000) : m_OnTimerFun(fun), m_interval(interval), m_isRunning(false) { CreateStopEvent(); DWORD dwThreadId; HANDLE hThread = CreateThread(NULL, 0, ThreadFun, (void*)this, 0, &dwThreadId); } virtual ~CWin32Timer() { Stop(); ReleaseStopEvent(); } private: static DWORD CALLBACK ThreadFun(void* para) { CWin32Timer* obj = (CWin32Timer*)para; if(0 == obj) return 1; obj->SetIsRunning(true); BOOL bRet; MSG msg; PeekMessage(&msg,NULL,WM_USER,WM_USER,PM_NOREMOVE); UINT timerid = ::SetTimer(NULL, 111, obj->m_interval, obj->m_OnTimerFun); while ((bRet = GetMessage(&msg,NULL,0,0))!=0) { if (bRet==-1) { // handle the error and possibly exit } else { TranslateMessage(&msg); DispatchMessage(&msg); } //檢查到退出信號就退出線程 if(VOS_ERR_QUE_TIMEOUT != VOS_WaitEvent(&obj->m_StopThreadEvent, 0)) break; } KillTimer(NULL,timerid); obj->SetIsRunning(false); return 0; } void Stop() { if(!IsRunning()) return; VOS_SetEvent(&m_StopThreadEvent); while (IsRunning()) { VOS_Sleep(1); } } void SetIsRunning(bool state) { m_isRunning = state; } bool IsRunning() { return m_isRunning; } void CreateStopEvent() { VOS_CreateEvent(&m_StopThreadEvent); } void ReleaseStopEvent() { VOS_DestroyEvent(&m_StopThreadEvent); } private: TIMERPROC m_OnTimerFun; unsigned int m_interval; bool m_isRunning; VOS_Event m_StopThreadEvent; };
使用多媒體定時器封裝以下:code
#pragma once #include <windows.h> #include <mmsystem.h> #pragma comment(lib,"winmm") class CWinMultimediaTimer { public: CWinMultimediaTimer(LPTIMECALLBACK callBack, DWORD_PTR dwUser = 0, unsigned int interval = 1000) : m_timerID(0) { CreateTimer(callBack, dwUser, interval); } ~CWinMultimediaTimer() { DestroyTimer(); } private: bool CreateTimer(LPTIMECALLBACK callBack, DWORD_PTR dwUser, unsigned int interval) { TIMECAPS tc; UINT wTimerRes; //設置多媒體定時器 if(timeGetDevCaps(&tc,sizeof(TIMECAPS)) != TIMERR_NOERROR)//向機器申請一個多媒體定時器 return false; //得到機器容許的時間間隔(通常可達到1毫秒) wTimerRes = min( max(tc.wPeriodMin, 1), tc.wPeriodMax); //調用回調函數timerback(),wTimerID爲定時器ID.TIME_PERIODIC表週期性調用,TIME_ONESHOT表只產生一次事件 m_timerID = timeSetEvent(interval, wTimerRes, callBack, dwUser, TIME_PERIODIC); if(m_timerID == 0) return false; return true; } //刪除定時器 void DestroyTimer() { if (!m_timerID) return; timeKillEvent(m_timerID); m_timerID = 0; } private: MMRESULT m_timerID; };