前言
有时候执行一个任务的时候,需要一直不断的采集数据,如果把采集数据的任务放在主任务,将会造成主任务的阻塞,通常的做法是将采集数据的任务创建一个子线程来完成。但是还有另一种方法,是通过定时器来定时采集数据。这样可以避免线程使用的复杂性,也更加容易调试。下面就列举了一个C/C++定时器的例程!
话不多说,直接放例程!
1.cMyTimer.h
代码如下:
#pragma once
#include "string"
#include "list"
using namespace std;
struct stTimer
{
unsigned timeElapce; //定时器间隔运行时间
unsigned timeCreate; //定时器创建时间
unsigned timeLastRun; //定时器上次执行时间
unsigned id; //定时器ID号
int iParam; //预留参数
string strParam; //预留参数
bool bDel; //是否已被删除
stTimer()
{
timeCreate = 0;
timeLastRun = 0;
id = -1;
iParam = 0;
bDel = false;
}
};
typedef list<stTimer> stTimerList;
typedef list<stTimer>::iterator itTimerList;
class cMyTimer
{
public:
cMyTimer();
virtual ~cMyTimer();
//添加定时器
void AddTimer(unsigned timerId, unsigned timeMs,int param = 0,
char* p=NULL);
//删除定时器
void DeleteTimer(int id);
//定时器处理
virtual int OnTimer(int id,int iParam,string str) = 0;
//检测定时器运行
bool TimerRun();
//清除所有定时器
void ClearTimer();
//定时检测删除定时器
void CheckDelTimer();
private:
stTimerList m_timerList; //定时器列表
};
2.cMyTimer.cpp
代码如下:
#include "stdafx.h"
#include "cMyTimer.h"
#include "windows.h"
#include "process.h"
cMyTimer::cMyTimer()
{
}
cMyTimer::~cMyTimer()
{
ClearTimer();
}
void cMyTimer::ClearTimer()
{
for (itTimerList it = m_timerList.begin();it != m_timerList.end();++it)
{
it->bDel = true;
}
}
void CheckTimerRun(void* p)
{
cMyTimer* pTimer = (cMyTimer*)p;
if (pTimer == NULL)
{
return;
}
while(1)
{
pTimer->CheckDelTimer();
//检测是否有定时器要运行
if(!pTimer->TimerRun())
{
_endthread();
}
Sleep(20);
}
}
//添加定时器
void cMyTimer::AddTimer(unsigned timerId,unsigned timeMs,int param,char* p)
{
if (timeMs == 0)
{
return;
}
stTimer stTimerTemp;
stTimerTemp.bDel = false;
stTimerTemp.id = timerId;
stTimerTemp.iParam = param;
if (p != NULL)
{
stTimerTemp.strParam = p;
}
unsigned timeNow = GetTickCount();
stTimerTemp.timeCreate = timeNow;
stTimerTemp.timeLastRun = timeNow;
stTimerTemp.timeElapce = timeMs;
m_timerList.push_back(stTimerTemp);
if (m_timerList.size() == 1)
{
//说明此时是第一个定时器
_beginthread(CheckTimerRun,0,this);
}
}
//删除定时器
void cMyTimer::DeleteTimer(int id)
{
for (itTimerList it = m_timerList.begin();it != m_timerList.end();++it)
{
if (it->id == id)
{
it->bDel = true;
return;
}
}
}
//定时器处理
//int cMyTimer::OnTimer(int id,int iParam,string str)
//{
// return 1;
//}
//定时检测删除定时器
void cMyTimer::CheckDelTimer()
{
for (itTimerList it = m_timerList.begin();it != m_timerList.end();)
{
if (it->bDel)
{
m_timerList.erase(it);
it = m_timerList.begin();
continue;
}
++it;
}
}
bool cMyTimer::TimerRun()
{
if (m_timerList.size() == 0)
{
return false;
}
unsigned timeNow = GetTickCount();
for (itTimerList it = m_timerList.begin();it != m_timerList.end();++it)
{
if (timeNow-it->timeLastRun >= it->timeElapce)
{
it->timeLastRun = timeNow;
if(OnTimer(it->id,it->iParam,it->strParam) == 0)
{
//删除定时器
it->bDel = true;
}
continue;
}
}
return true;
}
3.Test.h
代码如下:
#pragma once
#include "cMyTimer.h"
using namespace std;
class Derived : public cMyTimer //派生类
{
public: //公有的
Derived(); //构造函数
~Derived(); //析构函数:清除所有定时器
//定时器回调函数
virtual int OnTimer(int id, int iParam, string str);
};
4.Test.c
代码如下:
#include "Test.h"
#include "windows.h"
#include "process.h"
#include <conio.h> //_kbhit()
Derived::Derived() //派生类构造函数
{
}
Derived::~Derived() //派生类析构函数
{
}
//纯虚函数在派生类一定要实现
int Derived::OnTimer(int id, int iParam, string str)//定时器处理
{
static long num; //静态变量
printf("num=%d\r\n", num++);
return 1;
}
int main(int argc, char* argv[])
{
Derived Test; //派生类实例化
Test.AddTimer(0, 1000); //增加一个定时器0,定时时间为1000ms
Test.OnTimer(0,0,""); //调用定时器0处理函数。
while (!_kbhit())
{
}
Test.DeleteTimer(0); //删除定时0
return 0;
}
想要实现定时器功能,首先得创建一个定时器.设定好定时器的定时器事件:
通过函数void AddTimer(unsigned timerId, unsigned timeMs, int param = 0, char* p = NULL); 创建好一个指定 定时时间和定时器ID 的定时器.
然后再通过派生类函数 int OnTimer(int id,int iParam,string str); 实现需要定时执行的任务!
工程框图
如图所示:
执行结果
如图所示:
结果:1000ms打印一次!!!