实现定时器管理类
来源:互联网 发布:java下载手机版 编辑:程序博客网 时间:2024/04/29 15:07
一、定时器的用途
定时器在各种通信中有重要的用途。
二、定时器要实现的功能
根据指定的时间间隔产生定时器事件,并达到指定的精度。精度一般由定时器的采样精度相关,也就是和定时器硬件有关。在普通PC中,可以使用多媒体定时器获得10微秒以上的精度。
三、 C++中实现定时器的关键
在C++中实现定时器有几个问题要解决:
1、 如何在一个类中管理多个定时器
常见的使用方式中,定时器是一个事件ID和定时间隔的的“键—值”对。CMap是一个dictionary collection class,采用哈希表查找方式来定位,速度十分快,可以尽可能少影响定位精度。但是光保存一个定时间隔键值对还不行,因为不知道当前的定时器计数值(旧preTicks),故还要一个CMap来保存当前ticks。
因此一个定时器对应CMap中的一个“键—值”对。要管理这些定时器,只需要在线程函数中轮询当前定时器的nowTicks,并取得触发间隔elapseTicks,通过比较nowTicks – preTicks > elapseTicks 判断是否到了临界点,掌握定时事件触发时机。
这些工作全由定时器管理类来调度。
2、 使用者(类)应该如何接受定时器事件
可以利用事件或者C++中的虚函数的方式来让使用者(类)接受定时器触发事件,即处理定时器事件的函数被调用。我使用C++抽象类来完成这个工作。
即定义一个定时器事件抽象类,这个抽象类的实现类要成为定时器类的成员变量。当线程判断到定时器触发时,调用这个抽象类的事件处理函数(根据虚拟函数机制的了解,实际调用的实现类的处理函数)。
从上可以看出,如果使用者(类)要用定时器,必须实现定时器抽象类。
3、 谁来启动定时器线程,使用者(类)如何使用定时器管理类来定时。
当然应该由定时器管理类来管理定时线程的启动。使用者要使用定时,必须先实现定时器抽象类,并创建定时器管理类的一个实例,作为其成员变量。
四、 实现
(一)定义定时器抽象类
class ITimerEvent
{
public:
ITimerEvent();
virtual ~ITimerEvent();
void virtual OnTimer(UINT nIDEvent)=0;
};
(二)管理类
class CManTimer
{
public:
CManTimer(ITimerEvent* pEvent);
ITimerEvent* m_pTimerEvent;
virtual ~CManTimer();
void SetTimer(UINT nIDEvent, LARGE_INTEGER nElapse);
void KillTimer(int nIDEvent);
bool Start();
static DWORD WINAPI ThreadProc(LPVOID lpParameter );
HANDLE m_hMutex;
HANDLE m_hThread;
DWORD m_dwThreadId;
BOOL Lock(DWORD dwMilliSec = INFINITE)
{
if( WaitForSingleObject(m_hMutex,dwMilliSec) == WAIT_OBJECT_0)
return TRUE;
return FALSE;
}
BOOL Unlock(DWORD dwMilliSec = INFINITE)
{
return ReleaseMutex(m_hMutex);
}
void Destory();
void TimerProc();
private:
CMap<UINT,UINT,LARGE_INTEGER,LARGE_INTEGER> m_ElapseMap;
CMap<UINT,UINT,LARGE_INTEGER,LARGE_INTEGER> m_TickMap;
}
以下介绍几个关键成员函数的实现:
void CManTimer::SetTimer(UINT nIDEvent, LARGE_INTEGER nElapse)
{
Lock();
m_ElapseMap.SetAt(nIDEvent, nElapse);
LARGE_INTEGER nCurrentTicks = 0;
QueryPerformanceCounter(&nCurrentTicks);
m_TickMap.SetAt(nIDEvent, nCurrentTicks);
Unlock();
}
void CManTimer::KillTimer(int nIDEvent)
{
Lock();
m_ElapseMap.RemoveKey(nIDEvent);
m_TickMap.RemoveKey(nIDEvent);
Unlock();
}
DWORD WINAPI ThreadProc(LPVOID lpParameter )
{
CManTimer* pManTimer = (CManTimer*) lpParameter;
pManTimer->TimerProc();
return 0;
}
void CManTimer::TimerProc()
{
while(1)
{
if(!m_bContinue)
{
ExitThread(0);
}
try
{
POSITION pos = m_ElapseMap.GetStartPosition();
UINT nIDEvent;
LARGE_INTEGER nElapse;
LARGE_INTEGER dTicks;
while (pos != NULL)
{
m_ElapseMap.GetNextAssoc( pos, nIDEvent, nElapse );
m_TickMap.Lookup(nIDEvent,dTicks);
LARGE_INTEGER nCurrentTicks = 0;
QueryPerformanceCounter(&nCurrentTicks);
if(nCurrentTicks - dTicks > nElapse)
{
m_pTimerEvent->OnTimer(nIDEvent);
SetTimer(nIDEvent,nElapse);
}
}
}
catch ( ...) {
TRACE("ManTimer Exception/n");
}
}
}
- 实现定时器管理类
- 定时器管理
- C++Builder 动态生成定时器,创建定时器管理类
- Linux内核中的定时器的实现与管理
- 《Linux内核与实现》——定时器与时间管理
- Quartz定时器可视化管理功能的简单实现
- 定时器 实现
- 定时器实现
- 读薄《Linux 内核设计与实现》(5) - 定时器、时间管理和内存管理
- 4.时间管理、定时器管理
- Windows定时器管理
- 定时器和时间管理
- 软件定时器管理浅见
- spring的定时器管理
- Doubango 定时器管理用法
- AMPS:定时器管理
- spring定时器管理
- oracle 定时器动态管理
- congratulation to myself for a CSDN passport
- 测试
- C++学习摘要之二:构造函数和析构函数
- IT从业人员必看的10个论坛
- asp.net 发送邮件代码
- 实现定时器管理类
- 如何对DataTable 进行检索和排序
- sql中删除部分重复的语句
- 常用的大数运算库的地址
- 用Diff和Patch工具维护源码
- 毕业设计的开发总结
- The Shawshank Redemption,永恒的经典!
- 利用SQL Server 2000进行硬盘文件的移动
- SQL Server 连接中四种最常见错误