设置定时器的方法如下:
UINT_PTR SetTimer(
HWND hWnd,
UINT_PTR nIDEvent,
UINT uElapse,
TIMERPROC lpTimerFunc
);
关于这个函数,MSDN上有解释,其中对lpTimerFunc解释如下:
lpTimerFunc
从这段文字中,不难推测当调用SetTimer设置定时器后,系统会定时的发送一个WM_TIMER消息包给应用程序消息队列,而lpTimerFunc 函数则处理这个触发的消息,现在有个问题,如果lpTimerFunc函数处理的时间超过uElapse的时间间隔设置,或者有个死循环,此时会是什么情况呢?
要理解这个问题,仅仅需要区别定时器与线程的区别,定时器虽然消息是由系统内核发出,但是处理则是由窗口回调函数WndProc处理,而线程则是由内核在调度,说白了就是定时器是一个线程中处理函数。 lpTimerFunc 其实是在WndProc中被调用的,WndProc在没有处理完成一个消息的处理时是不会重入,因此如果定时器处理的时间超过了时间设置间隔,是不会重入的,如果定时器中出现死循环,那么WndProc将没法返回,自然没法处理其它的消息,此时主窗口就没有响应了。
OK,分析完毕.
下面是一些网友的讨论
我看了“windows程序设计”中关于定时器的描述。书中说定时器也是消息出发,并且不是异步的。那是不是说OnTimer中处理的过程独占整个主线程呢?也就是说定时器的作用是在主线程的执行路径近似中等间隔的插入处理过程。这样的话定时器的触发和主线程的执行都可能相互影响。
但是,如果某个间隔为一秒的定时器在OnTimer中需要处理的时间多于一秒,那么应该会出现这段处理过程的重复执行,那么要不要考虑数据的同步呢?
请高手执教,谢谢。 问题点数:20、回复次数:11Top
1 楼Featured(我握着爱情的门票静静排队……)回复于 2005-10-09 22:57:53 得分 3
那是不是说OnTimer中处理的过程独占整个主线程呢?
是的,定时器虽然看似不受主线程阻塞的影响,其实它还是在主线程中,并没有开另外的线程。(但是同样也存在线程被切换的现象。)
如果某个间隔为一秒的定时器在OnTimer中需要处理的时间多于一秒,那么应该会出现这段处理过程的重复执行,那么要不要考虑数据的同步呢?
要的Top
2 楼xtaddqqug(王中)回复于 2005-10-09 23:10:42 得分 2
当然要Top
3 楼pomelowu(羽战士)回复于 2005-10-09 23:12:27 得分 3
如果某个间隔为一秒的定时器在OnTimer中需要处理的时间多于一秒,那么应该会出现这段处理过程的重复执行,那么要不要考虑数据的同步呢?
要的
__________
不同意。虽然是同一线程中的插入操作,但是也要等函数返回才能插入。Top
4 楼stephen_young()回复于 2005-10-10 08:19:38 得分 0
如果某个间隔为一秒的定时器在OnTimer中需要处理的时间多于一秒,那么应该会出现这段处理过程的重复执行,那么要不要考虑数据的同步呢?
要的
__________
不同意。虽然是同一线程中的插入操作,但是也要等函数返回才能插入。
---------------------------------
我比较赞同这个观点,既然都是在同一个线程,应该不会出现竞争。Top
5 楼Mackz(在相互)回复于 2005-10-10 08:55:41 得分 3
WM_TIMER消息会被忽略,如果一个WM_TIMER消息正在处理,新的WM_TIMER消息不会产生,因此不存在函数重入的问题。类似的还有WM_PAINT消息。Top
6 楼Featured(我握着爱情的门票静静排队……)回复于 2005-10-10 09:04:37 得分 3
试过,的确如 pomelowu(羽战士) 和 Mackz(在相互) 所说,不会重入。
Mackz 也给出了令人信服的理由:如果一个WM_TIMER消息正在处理,新的WM_TIMER消息不会产生。
Top
7 楼nlstone(天外流星)回复于 2005-10-10 09:32:09 得分 3
不会重入是确定的,但WM_TIMER真的不会产生吗?我的印像中当debug ontimer时,当一次ontimer中断了一段时间(debug)再F5通过后,会连续有若干个ontimer被执行
从感觉上timer消息是被触发了的并加上了消息对列(但这个时候并没有去取这个消息,所以当然不会重入),当然,也可能是某种机制使得一个超时的ontimer结束后,立即产生一个timer消息到消息对列
Top
8 楼pomelowu(羽战士)回复于 2005-10-10 09:47:06 得分 0
同上。WM_TIMER是会产生的,不过如果多个相同WM_TIMER排在一起,会被合并。
另,WM_TIMER的优先度是最低的。Top
9 楼djfu(飞龙在天)回复于 2005-10-10 10:00:17 得分 3
如果某个间隔为一秒的定时器在OnTimer中需要处理的时间多于一秒,那么应该会出现这段处理过程的重复执行,那么要不要考虑数据的同步呢?
========================================================================================
定时器的定时事件是不会累积的。即:如果规定的时间达到,而定时处理函数还没有执行,那么会从消息队列里面移除这个定时的消息的。Top
10 楼wltg2001(红猪)回复于 2005-10-10 10:14:31 得分 0
好像窗口处理程序本身都是不可重入的,也就是说当窗口处理程序在处理一个消息时,只有等它处理完后才会响应下一个消息。Top
11 楼djfu(飞龙在天)回复于 2005-10-10 10:26:42 得分 0
wltg2001(红猪)
===========================
NO, 在主消息循环里面消息不是同步处理的。而是分派消息(::DispatchMessage),分派完毕,即取下一消息,分派就是直接指定一个处理消息的对象或接受者,所以,消息处理并不需要等待。