这几天在用MFC做有关定时器的东西,发现MFC自带的定时器方式SetTimer方式不适合用于频繁重新计时的方式,过多地Stop和SetTimer程序会死掉,因此,自已用线程的方式做了一个定时器类:
#pragma once #include "afxwin.h" #define ONESHOT 0 #define PERIOD 1 typedef int (*tp_ontimer)(void *param); class CTboxTimer { public: CTboxTimer(void); ~CTboxTimer(void); protected: DWORD m_start_tick; UINT m_timeout; public: static UINT CounterThread(void * param); protected: bool m_run_flag; public: void init(int mode,int timeout, tp_ontimer handle,void *param); protected: tp_ontimer m_onhandle; public: void init(void); void SetTimeouet(int timeout); void SetOnhandle(tp_ontimer handle,void *param); protected: CWinThread *m_thread; public: int Start(void); void Stop(void); void Restart(void); protected: void *m_param; int m_mode; };
#include "StdAfx.h" #include "TboxTimer.h" CTboxTimer::CTboxTimer(void) : m_start_tick(0) , m_timeout(0) , m_run_flag(false) ,m_onhandle(NULL) ,m_thread(NULL) , m_param(NULL) , m_mode(0) { } CTboxTimer::~CTboxTimer(void) { } UINT CTboxTimer::CounterThread(void * param) { CTboxTimer *timer =(CTboxTimer *)param; while(timer->m_run_flag){ if(GetTickCount() -timer->m_start_tick >=timer->m_timeout){ //do something here if(timer->m_onhandle !=NULL){ if(0 !=(*timer->m_onhandle)(timer->m_param)){ timer->Stop(); break; } if(timer->m_mode ==ONESHOT){ timer->Stop(); break; } timer->m_start_tick =GetTickCount();//更新记时起点 } } Sleep(20); } return 0; } void CTboxTimer::init(int mode,int timeout, tp_ontimer handle=NULL,void *param=NULL) { m_mode =mode; m_timeout =timeout; m_onhandle =handle; m_param =param; } void CTboxTimer::init(void) { m_timeout =0; m_onhandle =NULL; } void CTboxTimer::SetTimeouet(int timeout) { m_timeout =timeout; } void CTboxTimer::SetOnhandle(tp_ontimer handle,void *param) { m_onhandle =handle; m_param =param; } int CTboxTimer::Start(void) { if(m_run_flag){ return 0; } m_run_flag =true; m_start_tick =GetTickCount(); m_thread =AfxBeginThread(CounterThread,this); if(m_thread ==NULL){ m_run_flag =false; return -1; } return 0; } void CTboxTimer::Stop(void) { m_run_flag =false; } void CTboxTimer::Restart(void) { m_start_tick =GetTickCount(); }