65.9K
CodeProject 正在变化。 阅读更多。
Home

CMultimediaTimer - 一个周期性计时器类

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.13/5 (7投票s)

2002年3月28日

1分钟阅读

viewsIcon

72195

downloadIcon

1675

CMultimediaTimer 使用 Windows Multimedia Timer API 实现周期性计时器

CMultimediaTimer

CMultimediaTimer 使用 Windows 多媒体定时器 API 实现一个简单的周期性定时器。

注意:多媒体定时器实际上是一个独立的高优先级线程,因此所有正常的多线程问题都适用。与工作线程一样,由于 CWinThread 局部存储中存储的句柄映射“魔咒”,不应直接从定时器回调中调用 MFC 对象。

CMultimediaTimer 不依赖于 GUI,因为我用它来处理控制台应用程序中的周期性活动。

要启动定时器

  • CMultimediaTimerCallback 派生一个循环处理类,并重写纯虚方法 OnLoop()
  • 创建一个 CMultimediaTimer,并将派生循环处理类的实例作为构造函数参数传递。
  • 使用循环周期(以毫秒为单位)作为第一个参数调用 Start() 方法。

使用示例:

MyLoopHandlerClass handler;
CMultimediaTimer timer(handler);
timer.Start(20,1); //Run loop at 50Hz with the resolution set to 1ms

CMultimediaTimerCallback 是必须重写以支持循环处理的回调接口。
我们将循环处理与主 timer 类分离,以防止从 OnLoop() 内部调用 CMultimediaTimer 方法,这可能会导致竞争条件。

////////////////////////////////////////////////////////////////////////////////////
// CMultimediaTimerCallback  -  The callback support interface
////////////////////////////////////////////////////////////////////////////////////
class CMultimediaTimerCallback
{
public:
    CMultimediaTimerCallback(){}
    virtual ~CMultimediaTimerCallback(){}

public:
    virtual bool OnLoop()=0;    //Must Override timer will stop if return false
    virtual void OnStarted(){}  //Overrideable called when timer started sucessfully
    virtual void OnStopped(){}  //Overrideable called after timer stopped
};

CMultimediaTimertimer 类。
要使用,只需从 CMultimediaTimer 派生一个类并重写 OnLoop()。接下来,使用周期(以毫秒为单位)作为第一个参数调用 Start 方法。

////////////////////////////////////////////////////////////////////////////////////
// CMultimediaTimer  -  A simple periodic timer
////////////////////////////////////////////////////////////////////////////////////
class CMultimediaTimer
{
public:
    CMultimediaTimer(CMultimediaTimerCallback& callback);
    virtual ~CMultimediaTimer();

    //Start the periodic timer, OnLoop() will be called every nPeriodMs 
    //milliseconds. Start() returns false if failed and nError returns the error 
    //code
    bool Start(UINT nPeriodMs,
               MMRESULT& nError,
               UINT nResolutionMs = cDefaultTimerResolution);

    //Same as above but no error code returned
    bool Start(UINT nPeriodMs,UINT nResolutionMs = cDefaultTimerResolution)
              {MMRESULT nErr; return Start(nPeriodMs,nErr,nResolutionMs);}

    //Stop the timer
    void Stop();

    //Is the timer running
    bool Active()const {return m_TimerId != 0;}

    //Period set while running
    UINT GetPeriodMs()const {return m_TimerPeriod;}

    //Resolution set while running
    UINT GetResolutionMs()const{return m_TimerResolution;}

private:
    bool CheckMarker()const;
    void ResetPeriodResolution();
    void DoLoop();

private:
    CMultimediaTimerCallback& m_Callback;    //The loop callback
    UINT m_TimerPeriod;                      //Timer period in milliseconds
    UINT m_TimerResolution;                  //Timer resolution in milliseconds
    UINT m_TimerId;                          //ID of timer thread
    bool m_EndTimer;                         //Flag to force timer to stop from loop
    FLCriticalSection m_StopCriticalSection; //section to protect multi access 
                                             // to Stop()

private:
    DWORD m_Marker;                          //Paranoia check
    friend void CALLBACK mmTimerProc(UINT,UINT,DWORD,DWORD,DWORD); //Callback
};

祝您循环愉快!

许可证

本文未附加明确的许可证,但可能在文章文本或下载文件本身中包含使用条款。如有疑问,请通过下面的讨论区联系作者。

作者可能使用的许可证列表可以在此处找到。

© . All rights reserved.