VC++使用SDL定时器替代Windows窗口定时器消息(附源码)
Posted dvlinker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++使用SDL定时器替代Windows窗口定时器消息(附源码)相关的知识,希望对你有一定的参考价值。
在Windows应用程序中我们常常会使用到Windows窗口相关的定时器,去实现定时的目的。窗口定时器使用起来也确实方便,但窗口定时器在使用时有一定的缺陷,所以在某些特殊的场景下我们需要用其他类型的定时器来取代Windows窗口定时器,今天我们就来看看和Windows窗口无关的SDL定时器。
1、Windows窗口定时器介绍
Windows窗口定时器时和窗口相关的,是运行在UI主线程中的。先调用SetTimer函数设定窗口定时器(创建定时器时会设定一个定时器id),在定时时间到了后,系统会给窗口投递一个WM_TIMER消息(消息中会携带定时器消息对应的id)。代码中收到定时器消息后,比对定时器消息对应的id,然后去执行对应的定时任务。
2、Windows窗口定时器缺陷
Windows窗口定时器消息WM_TIMER是个优先级比较低的消息,如果当前UI线程中在频繁产生大量的消息,消息队列中有大量的消息等待处理,那么低优先级的WM_TIMER消息就会被丢弃掉,这样定时就出问题了,对应的定时任务也就无法得到执行了。
以前听说WM_TIMER消息的优先级比较低,在大量窗口消息等待被处理时,WM_TIMER消息会被丢弃掉。对这种说法一直半信半疑,直到有次在项目中开发某个功能时遇到这样的问题,才深有体会。
所以在窗口定时器出现问题时,我们就需要使用其他定时器了。本文我们来介绍一下SDL开源库中提供的定时器。
3、SDL开源库中提供的SDL定时器
SDL开源库中提供的定时器是与窗口无关的,是在一个独立的线程中去计时的,是与UI线程无关的,所以即使UI线程消息再多再忙碌,SDL定时器都是比较准确的。
SDL开源库中提供了SDL_AddTimer、SDL_RemoveTimer API接口,使用起来很方便。我们通过调用SDL_AddTimer创建定时器,并设定定时器的回调函数,如下:
// 创建定时器,设定定时器回调函数
if ( m_dwSdlTimerID == 0 )
m_dwSdlTimerID = SDL_AddTimer( 100, CbSdlTimerFunc, (void *)this );
// 定时器回调函数
static Uint32 SDLCALL CbSdlTimerFunc( Uint32 dwInterval, void *param )
// 给目标窗口投递窗口自定义消息,告诉窗口定时器消息来了,可以执行指定的定时任务了
CXXXXWnd* pThis = (CXXXXWnd*)param;
::PostMessage( pThis->GetHWND(), WM_XXXXXXXXXXXX, 0, 0 );
return dwInterval;
当定时时间到了,就会调用创建时设定的回调函数了。
注意定时执行的任务不能直接放到回调函数中去执行,因为回调函数执行在定时器线程中的,和主线程不在同一个线程,不能将定时任务放在回调函数中执行,否则可能会导致定时器线程的堵塞。一般情况下,在回调函数中禁止执行业务代码,因为在回调函数中的执行业务代码,可能会导致回调函数所在线程的堵塞!所以,在回调函数中我们需要给主线程投递通知消息,在主线程中执行定时任务。
在不用定时器时,调用SDL_RemoveTimer函数将定时器销毁掉,如下:
if ( m_dwSdlTimerID != 0 )
SDL_RemoveTimer( m_dwSdlTimerID );
m_dwSdlTimerID = 0;
4、SDL定时器库的下载
如果要使用SDL定时器,可以去下载开源的SDL库,也可以下载此处提供的裁剪版定时器库,地址如下:
链接:https://pan.baidu.com/s/1MvR1ZYEIDaXeZyzi1E9uMg
提取码:o1e7
以上是关于VC++使用SDL定时器替代Windows窗口定时器消息(附源码)的主要内容,如果未能解决你的问题,请参考以下文章