VC++几种定时器使用方法的归纳

本文探讨了MFC中实现定时器的多种方法,包括WM_TIMER、WaitableTimer、多线程Sleep、混合WM_TIMER与多线程等方案,并提到了多媒体定时器和DirectX定时器的可能性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        在游戏编写中,我遇到一个现象:在连续按键的相应过程中,WM_TIMER消息一直没有得到相应。

        查阅网上的资料后发现,WM_TIMER的消息属于最低优先级的消息,当线程的队列中没有其他消息时,才检索该消息。而且设置的定时器不精确(大概57ms左右的精度),所以会出现了延迟的结果。于是,我想看看有没有其他的定时器方式,大致有以下几个方式:

        1.WM_TIMER:SetTimer,OnTimer,KillTimer这样的使用方式(最简单的);

        2.等待定时器(WaitableTimer):

        (1)一种是,多线程+WaitableTimer实现定时器功能(未使用响应函数的方法),相关代码如下:

int CWaitableTimerTestView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO:  在此添加您专用的创建代码
	// 创建定时器线程,并立即执行
	m_hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)TimerThreadProc, (LPVOID)this, 0, &ThreadID);
	return 0;
}
// 定时器线程执行函数
void TimerThreadProc(LPVOID lpArg)
{
	// 多线程+WaitableTimer实现定时器功能(未使用定时响应函数版本)
	CWaitableTimerTestView *pView = (CWaitableTimerTestView *)lpArg;
	// 创建等待定时器
	pView->m_hTimer = CreateWaitableTimer(NULL, FALSE, _T("MyWaitableTimer"));// 自动归零
	if (NULL == pView->m_hTimer)
	{
		AfxMessageBox(_T("Can't create waitable timer!"));
		return;
	}
	LARGE_INTEGER liDueTime;
	liDueTime.QuadPart = -2000000LL;// 200ms=200*10^6ns=2*10^6(100ns)

	// 设置等待定时器
	if (FALSE == SetWaitableTimer(pView->m_hTimer, &liDueTime, 200, NULL, NULL, FALSE))
	{
		AfxMessageBox(_T("SetWaitableTimer Failed!"));
		return;
	}
	while (pView->m_bTimerThreadRun)
	{
		if (WaitForSingleObject(pView->m_hTimer, INFINITE) != WAIT_OBJECT_0)
		{
			pView->MessageBox("WaitForSingleObject failed ");
		}
		else
		{
			pView->data++;
		}
	}
	CancelWaitableTimer(pView->m_hTimer);
	CloseHandle(pView->m_hTimer);

	return;
}
        (2)另外一种是,多线程+WaitableTimer实现定时器功能(使用响应函数的方法),相关代码如下:

// 定时器线程执行函数
void TimerThreadProc(LPVOID lpArg)
{
	// 多线程+WaitableTimer实现定时器功能(使用定时响应函数版本)
	CWaitableTimerTestView *pView = (CWaitableTimerTestView *)lpArg;
	// 创建等待定时器
	pView->m_hTimer = CreateWaitableTimer(NULL, FALSE, _T("MyWaitableTimer"));// 自动归零
	if (NULL == pView->m_hTimer)
	{
		AfxMessageBox(_T("Can't create waitable timer!"));
		return ;
	}
	LARGE_INTEGER liDueTime;
	liDueTime.QuadPart = -2000000LL;// 200ms=200*10^6ns=2*10^6(100ns)
	
	while (pView->m_bTimerThreadRun)
	{
		// 设置等待定时器
		if (FALSE == SetWaitableTimer(pView->m_hTimer, &liDueTime, 200, (PTIMERAPCROUTINE)TimerAPCProc, (LPVOID)lpArg, FALSE))
		{
			AfxMessageBox(_T("SetWaitableTimer Failed!"));
			return;
		}
		else// 如果没有,就不会调用TimerAPCProc
		{
			SleepEx(
				INFINITE,     // Wait forever
				TRUE);       // Put thread in an alertable state
		}
	}
	CancelWaitableTimer(pView->m_hTimer);
	CloseHandle(pView->m_hTimer);
	return;
}
// 远程调用
VOID CALLBACK TimerAPCProc(LPVOID lpArg, DWORD dwTimerLowValue, DWORD dwTimerHighValue)
{
	CWaitableTimerTestView *pView = (CWaitableTimerTestView*)lpArg;
	if (WaitForSingleObject(pView->m_hTimer, INFINITE) != WAIT_OBJECT_0)
	{
		pView->MessageBox("WaitForSingleObject failed ");
	}
	else
	{
		pView->data++;
	}
}

        3.多线程+Sleep延时函数:(与2类似)

           另一个线程一直运行,每个一定时间运行一次,Sleep(mSec);

           注意此种方式在调用OnDraw(GetDC)方法时,会出现pDoc重复获取的assert不合法、闪烁及绘制错误等问题

// 定时器线程执行函数
void TimerThreadProc(LPVOID lpArg)
{
	// 多线程+Sleep(msec)实现定时器功能
	CWaitableTimerTestView *pView = (CWaitableTimerTestView *)lpArg;
	while (pView->m_bTimerThreadRun)
	{
		pView->data++;
		Sleep(200);
	}
}

        4.采用多线程+WM_TIMER消息混合方式:

           多线程固定时间计算各图像元素的位置,而WM_TIMER通知定时绘图显示,在WM_KEYDOWN消息频繁时,由于WM_KEYDOWN处理过程中也要采用OnDraw方法重绘整个屏幕,故也可以达到定时移动背景和敌机相关的定时移动。
5.采用多媒体定时器,更加精确。(还未深入研究过)

        6.DirectX中的定时器(还未深入研究过)

以上是我目前为止查到能在MFC中使用的定时器方式,欢迎大家讨论补充,互相学习,共同进步!


01-22 2987
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值