用Win32,写一个自定义的定时器

创建一个自定义定时器,其重点在于如何定时。

我的解决方案是适合采用观察者模式,分为主题类CPdsTimerSub和观察者类CPdsTimerObj ,这个两个类分别继承IPdsTimerSub和IPdsTimerObj接口 .

#pragma once
#include "stdafx.h"
#include <map>

class IPdsTimer
{
public:
IPdsTimer(){};
virtual ~IPdsTimer(){};
public:
    /// @brief响应函数
virtual void OnTimer() = 0;
};


class IPdsTimerObj : public IPdsTimer
{
public:
IPdsTimerObj(){};
virtual ~IPdsTimerObj(){};
public:
/// @brief设置定时器,nId定时器ID,nTimerSplit间隔时间
virtual void SetTimer(unsigned int nId, unsigned int nTimerSplit) = 0;
/// @brief设置新的定时器,并返回新的定时器ID
virtual unsigned int SetNewTimer(unsigned int nTimerSplit) = 0;
/// @brief销毁定时器
virtual void KillTimer(unsigned int nId) = 0;
public:
/// @brief计时
virtual void CountTime() = 0;
};


class IPdsTimerSub
{
public:
IPdsTimerSub(){};
virtual ~IPdsTimerSub()
{
m_mapIdTimers.clear();
};
public:
/// @brief注册定时器
virtual bool RegisterTimer(unsigned int nId, IPdsTimerObj* timerObj) = 0;
/// @brief反注册定时器
virtual bool UnRegisterTimer(unsigned int nId) = 0;
/// @brief通知所有定时器
virtual void NotifyAllTimer() = 0;
public:
std::map<unsigned int, IPdsTimerObj*> m_mapIdTimers;
};

在主题类中创建一个线程,线程每隔一秒,去通知所有观察者类过了一秒了。

#pragma once
#include "IPdsTimer.h"
#include <iostream>
#include <windows.h>

class CPdsTimerSub : public IPdsTimerSub
{
public:
static IPdsTimerSub* GetInstance();
public:
virtual bool RegisterTimer(unsigned int nId, IPdsTimerObj* timerObj);
virtual bool UnRegisterTimer(unsigned int nId);
virtual void NotifyAllTimer();
protected:
CPdsTimerSub();
virtual ~CPdsTimerSub();

private:
static IPdsTimerSub* m_Instance;
};

#include "stdafx.h"
#include "PdsTimerSub.h"

IPdsTimerSub* CPdsTimerSub::m_Instance = nullptr;
static unsigned int g_nThreadId = 10086;

DWORD WINAPI ThreadFun(LPVOID pM)
{
IPdsTimerSub* pTimerSub = (CPdsTimerSub *)pM;

if(pTimerSub == nullptr){return 0;};

long lStartTime = GetTickCount();
while(1)
{
long lEndTime = GetTickCount();

while(lEndTime - lStartTime >= 1000)
{
pTimerSub->NotifyAllTimer();
lStartTime = lEndTime;
}
}

return 0;
}

CPdsTimerSub::CPdsTimerSub()
{

}
CPdsTimerSub::~CPdsTimerSub()
{
ExitProcess(g_nThreadId);
}

bool CPdsTimerSub::RegisterTimer(unsigned int nId, IPdsTimerObj* timerObj)
{
m_mapIdTimers.insert(std::make_pair(nId, timerObj));

return true;
}

bool CPdsTimerSub::UnRegisterTimer(unsigned int nId)
{
for(auto iter = m_mapIdTimers.begin()
; iter != m_mapIdTimers.end(); iter++)
{
if (iter->first == nId)
{
m_mapIdTimers.erase(iter);

return true;
}
}

return false;
}

void CPdsTimerSub::NotifyAllTimer()
{
for(auto elem : m_mapIdTimers)
{
elem.second->CountTime();
}
}

IPdsTimerSub* CPdsTimerSub::GetInstance()
{
if (m_Instance == nullptr)
{
m_Instance = new CPdsTimerSub();
HANDLE handle = CreateThread(NULL, 0, ThreadFun, m_Instance, 0, (LPDWORD)&g_nThreadId);
CloseHandle(handle);
}

return m_Instance;
}

这样的话,每个观察者类就可以自己去计时,时间到了,就去执行响应函数

#pragma once
#include "IPdsTimer.h"

class CPdsTimerObj : public IPdsTimerObj
{
public:
CPdsTimerObj(void);
virtual ~CPdsTimerObj(void);
public:
virtual void SetTimer(unsigned int nId, unsigned int nTimerSplit);
virtual unsigned int SetNewTimer(unsigned int nTimerSplit);
virtual void KillTimer(unsigned int nId);
virtual void OnTimer();
public:
virtual void CountTime();
private:
unsigned int m_nTimeSplit;
unsigned int m_nRealTime;
unsigned int m_nTimerId;
IPdsTimerSub*m_pPdsTimerSub;
};

#include "stdafx.h"
#include "PdsTimerObj.h"
#include "PdsTimerSub.h"

CPdsTimerObj::CPdsTimerObj(void)
: m_nTimeSplit(1000)
, m_nRealTime(0)
, m_nTimerId(0)
, m_pPdsTimerSub(nullptr)
{
m_pPdsTimerSub = CPdsTimerSub::GetInstance();
}


CPdsTimerObj::~CPdsTimerObj(void)
{

}

void CPdsTimerObj::SetTimer(unsigned int nId, unsigned int nTimerSplit)
{
m_nTimerId = nId;
m_nTimeSplit = nTimerSplit;

m_pPdsTimerSub->RegisterTimer(nId, this);
}

void CPdsTimerObj::KillTimer(unsigned int nId)
{
m_pPdsTimerSub->UnRegisterTimer(nId);
//m_nTimerId = 0;
}

void CPdsTimerObj::CountTime()
{
m_nRealTime++;

if ((m_nRealTime * 1000) >= m_nTimeSplit)
{
m_nRealTime = 0;
OnTimer();
}
}

void CPdsTimerObj::OnTimer()
{
printf("%d\n", m_nTimerId);
}

unsigned int CPdsTimerObj::SetNewTimer(unsigned int nTimerSplit)
{
if (m_pPdsTimerSub != nullptr)
{
unsigned int nNewId = 1235;//最好替换成随机获取数值的函数
while(true)
{
for(auto elem : m_pPdsTimerSub->m_mapIdTimers)
{
if (nNewId != elem.first)
{
SetTimer(nNewId, nTimerSplit);
KillTimer(m_nTimerId);

return nNewId;
}
}
nNewId++;
}
}

return 0;
}

测试如下:

#include "stdafx.h"
#include "PdsTimerObj.h"
#include "PdsTimerSub.h"


int _tmain(int argc, _TCHAR* argv[])
{
IPdsTimerObj *pTimerObj1 = new CPdsTimerObj();
pTimerObj1->SetTimer(1000, 1000);

IPdsTimerObj *pTimerObj2 = new CPdsTimerObj();
pTimerObj2->SetTimer(2000, 1000);
pTimerObj2->SetNewTimer(2000);

IPdsTimerObj *pTimerObj3 = new CPdsTimerObj();
pTimerObj3->SetTimer(3000, 1000);
pTimerObj3->KillTimer(3000);

while (true);

return 0;
}


猜你喜欢

转载自blog.csdn.net/chicaidecaiji/article/details/77727168