基于win32的定时器功能封装动态库:实现任务的延时执行

版权声明:本文为博主原创文章,未经博主允许不得转载。 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

猜你喜欢

转载自blog.csdn.net/haimianjie2012/article/details/82906335
今日推荐