版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haimianjie2012/article/details/82906335
首先,谈谈延时任务执行的产生背景,界面上每画一次线,调用一次啊算法,因为算法需要比较长时间,所以当多次画线时,界面上就会出现卡死的现象。为了提高用户体验,画线的时候不让其调用算法,而是让系统等待一定时间后,再调用算法。频繁画线,就会等画完线后再调用算法。
.IDtimer = ::SetTimer(HWND,UINT,UINT,TIMERPROC);
这样创建一个定时器将返回一个定时器IDtimer,在销毁定时器时调用KillTimer(NULL,IDtimer)。这种方式适合多次定时容易混淆定时器ID的程序,因为其返回值管理定时器ID,而不要自己去管理。
本文将运用为win32接口::SetTimer()实现任务的延时执行
#ifndef _ABSTRACTMPTLAZYTASK_H_
#define _ABSTRACTMPTLAZYTASK_H_
#ifndef MPTDLL
#define MPTEXPORT __declspec(dllimport)
#else
#define MPTEXPORT __declspec(dllexport)
#endif
#define LAZYTIMER_CONTINUE 1 ///< 定时器不会被取消,通过该值实现循环定时器功能
#define LAZYTIMER_STOP 0 ///< 定时器会被取消,通过该值实现定时器仅执行一次
/**
*@brief 任务抽象类
*表示一个需要延迟执行的任务
*/
class MPTEXPORT AbstractMptLazyTask
{
public:
/**
*执行任务,该方法由MptLazyTimer对象调用
*@return 返回 LAZYTIMER_CONTINUE 时表示不取消定时器,返回 LAZYTIMER_STOP 表示取消定时器
*@see LAZYTIMER_CONTINUE
*@see LAZYTIMER_STOP
*/
virtual int Run() = 0;
};
/**
*@brief 基于win32的定时器功能封装
*实现任务的延时执行
*/
class MPTEXPORT MptLazyTimer
{
public:
MptLazyTimer(void);
virtual ~MptLazyTimer(void);
/**
*设置定时器时间,单位毫秒
*@param[in] ms 定时器的时间
*/
void SetElapse(UINT ms);
/**
*执行任务
*@param[in] pTask 由使用者实现的任务对象
*@return
*/
int RunTask(AbstractMptLazyTask *pTask);
protected:
UINT m_elapseTime;
};
#endif
#include "StdAfx.h"
#include "MptLazyTimer.h"
// /* class AbstractMptLazyTask */
// AbstractMptLazyTask::~AbstractMptLazyTask()
// {
// }
/* class MptLazyTimer */
MptLazyTimer::MptLazyTimer(void)
:m_elapseTime(1000)
{
}
MptLazyTimer::~MptLazyTimer(void)
{
}
void MptLazyTimer::SetElapse(UINT ms)
{
m_elapseTime = ms;
}
#define DEF_TIMER_ID 1008
#define FIRST_TIMER_ELAPSE 500
static UINT_PTR gTimerID = 0;
static AbstractMptLazyTask *gpTask = NULL;
static void CALLBACK TimerProcFun(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{
if (gTimerID == idEvent)
{
int runRet = LAZYTIMER_STOP;
if (gpTask)
{
runRet = gpTask->Run();
}
if(LAZYTIMER_STOP == runRet && KillTimer(NULL, gTimerID))
{
gpTask = NULL;
gTimerID = 0;
}
}
}
int MptLazyTimer::RunTask(AbstractMptLazyTask *pTask)
{
int ret = LAZYTIMER_STOP;
gpTask = pTask;
do
{
if (NULL == gpTask)
{
break;
}
if (0 == gTimerID)
{
//返回定时器ID
gTimerID = ::SetTimer(NULL, DEF_TIMER_ID, FIRST_TIMER_ELAPSE, TimerProcFun);
ret = 0;
}
else
{
::SetTimer(NULL, gTimerID, m_elapseTime, TimerProcFun);
ret = 1;
}
} while (false);
return ret;
}
使用实例:
// 实现任务类
class TestRunTask:public AbstractMptLazyTask
{
private:
int m_count;
public:
TestRunTask():m_count(0)
{
}
virtual int Run()
{
m_count++;
printf("TestRunTask::Run() %d \r\n", m_count);
return 0;
}
};
// 测试
TEST(TestLazyTimerFunction, TestLazyTimer)
{
TestRunTask task;
MptLazyTimer mptLazyTimer;
mptLazyTimer.SetElapse(500); // 设置延迟500 ms
for (int i = 0; i < 5; i++)
{
printf("TestLazyTimer RunTask() %d \r\n", i);
mptLazyTimer.RunTask(&task); // 代码上连续执行5次任务,实际上仅执行一次
Sleep(200);
}
}
参考文献:https://blog.csdn.net/lcalqf/article/details/53020009?utm_source=copy