这几天在用MFC做有关定时器的东西,发现MFC自带的定时器方式SetTimer方式不适合用于频繁重新计时的方式,过多地Stop和SetTimer程序会死掉,因此,自已用线程的方式做了一个定时器类:
#pragma once
#include "afxwin.h"
#define ONESHOT 0
#define PERIOD 1
typedef int (*tp_ontimer)(void *param);
class CMyTimer
{
public:
CMyTimer(void);
~CMyTimer(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();
}