C++定时器实现详解

C++编程中,定时器是一种常见的需求,用于执行周期性或延时任务。Windows操作系统提供了多种定时器实现方式,但这些不同的实现方法可能会给初学者带来困惑。本文将介绍一种使用Windows API实现的简单定时器,并展示如何通过模板类来简化定时器的实现过程。

定时器的基本概念

定时器是一种计时工具,它能够在指定的时间间隔后触发一个事件。在C++中,定时器的实现通常依赖于操作系统提供的API。Windows操作系统提供了多种定时器API,例如CreateTimerQueueTimerSetTimer等。这些API各有特点,适用于不同的场景。

使用CreateTimerQueueTimer实现定时器

CreateTimerQueueTimer是Windows API中用于创建定时器的一种方法。它允许开发者指定一个回调函数,在定时器触发时执行。这种方法适用于执行短任务,因为它会在定时器线程中执行回调函数。

需要注意的是,Windows定时器的精度受到操作系统的限制,可能存在一定的误差。经过测试,发现定时器的分辨率在200毫秒以上的间隔时较为准确。

定时器的启动和停止

定时器的启动和停止是其核心功能。在本文的实现中,提供了两种方法来启动定时器:Start方法的默认实现允许定时器在指定的毫秒间隔后启动;第一个重载允许定时器立即启动,即第一次定时事件立即被调用;第二个重载允许定时器只被调用一次。

定时器的停止可以通过Stop方法实现。如果需要,在OnTimedEvent函数中也可以调用Stop方法来停止定时器。例如,可以在定时器被调用10次后停止定时器。

定时器的回调函数

定时器的回调函数是定时器触发时执行的函数。在本文的实现中,使用模板类TTimer来实现回调函数。这允许开发者指定一个类函数作为回调函数,通过SetTimedEvent方法设置。

CTimer实现了一个虚拟方法OnTimedEvent,该方法由定时器过程TimerProc调用。TTimer类继承自CTimer,并重写了OnTimerEvent方法,该方法调用用户定义的回调函数

线程安全的定时器事件计数

为了实现线程安全的定时器事件计数,本文的实现使用了InterlockedExchangeAddInterlockedExchange函数。这些函数提供了一种快速的互斥访问方式,允许在代码的任何地方读取或设置定时器事件计数。

使用代码示例

为了便于使用,本文的定时器实现被封装在单个文件TemplateTimer.h中。要使用这个定时器,只需将TemplateTimer.h包含到项目中,并按照测试代码TimerTest.cpp/.h中的示例进行实现。

代码实现

以下是定时器实现的核心代码:

#pragma once #include <atlbase.h> static void CALLBACK TimerProc(void *, BOOLEAN); ////////////////////////////////////////////////////////////////////////// // // class CTimer // class CTimer { public: CTimer() { m_hTimer = NULL; m_mutexCount = 0; } virtual ~CTimer() { Stop(); } bool Start(unsigned int interval, bool immediately = false, bool once = false) { if (m_hTimer) { return false; } SetCount(0); BOOL success = CreateTimerQueueTimer(&m_hTimer, NULL, TimerProc, this, immediately ? 0 : interval, once ? 0 : interval, WT_EXECUTEINTIMERTHREAD); return (success != 0); } void Stop() { DeleteTimerQueueTimer(NULL, m_hTimer, NULL); m_hTimer = NULL; } virtual void OnTimedEvent() { // Override in derived class } void SetCount(int value) { InterlockedExchange(&m_mutexCount, value); } int GetCount() { return InterlockedExchangeAdd(&m_mutexCount, 0); } private: HANDLE m_hTimer; long m_mutexCount; }; ////////////////////////////////////////////////////////////////////////// // // TimerProc // void CALLBACK TimerProc(void *param, BOOLEAN timerCalled) { CTimer* timer = static_cast(param); timer->SetCount(timer->GetCount() + 1); timer->OnTimedEvent(); } ////////////////////////////////////////////////////////////////////////// // // template class TTimer // template class TTimer : public CTimer { public: typedef void (T::*TimedFunction)(void); TTimer() { m_pTimedFunction = NULL; m_pClass = NULL; } void SetTimedEvent(T *pClass, TimedFunction pFunc) { m_pClass = pClass; m_pTimedFunction = pFunc; } protected: void OnTimedEvent() { if (m_pTimedFunction && m_pClass) { (m_pClass->*m_pTimedFunction)(); } } private: T *m_pClass; TimedFunction m_pTimedFunction; };

测试代码

#pragma once #include "TemplateTimer.h" class CTimerTest { public: void RunTest(); private: void OnTimedEvent1(); void OnTimedEvent2(); TTimer timer1; TTimer timer2; }; void CTimerTest::OnTimedEvent1() { printf("\nTimer 1 Called (count=%i)", timer1.GetCount()); } void CTimerTest::OnTimedEvent2() { printf("\nTimer 2 Called (count=%i)", timer2.GetCount()); } void CTimerTest::RunTest() { printf("Hit return to start and stop timers"); getchar(); timer1.SetTimedEvent(this, &CTimerTest::OnTimedEvent1); timer1.Start(1000); // Start timer 1 every 1s timer2.SetTimedEvent(this, &CTimerTest::OnTimedEvent2); timer2.Start(2000); // Start timer 2 every 2s getchar(); // Wait for return (stop) timer1.Stop(); // Stop timer 1 timer2.Stop(); // Stop timer 2 printf("\nTimers stopped (hit return to exit)"); getchar(); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485