zl程序教程

您现在的位置是:首页 >  其他

当前栏目

说说MsgWaitForMultipleObjects和队列状态

2023-09-14 09:10:44 时间

MsgWaitForMultipleObjects的危险之处在于,如果调用它的时候还有消息等待处理,这个时候调用就会挂起,因为MsgWaitForMultipleObjects只会在队列中出现一个新的事件的时候才会返回。

换句话说,让我们考虑下面的情景:
> PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)调用返回了TRUE,表明队列中有一个消息。
> 这个时候,不处理此消息,而是调用MsgWaitForMultipleObjects。

这个MsgWaitForMultipleObjects调用不会立即返回,即使这个时候,队列中确实有一个消息。因为PeekMessage已经告诉你队列中有一个消息了,而你只是故意将它忽略了。MsgWaitForMultipleObjects只会告诉你有”新”的消息,它会忽略掉你所知道的所有”旧”的消息。

下面是一个常见的错误流程:
> MsgWaitForMultipleObjects调用返回指示有一个消息。
> 这个时候,调用PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)并处理这个消息。
> 继续调用MsgWaitForMultipleObjects来等待更多的消息。

如果消息队列中有两条消息,则MsgWaitForMultipleObjects不会立即返回,因为没有新消息。但是,你故意忽略了一条旧消息。

当MsgWaitForMultipleObjects告诉你消息队列中有消息时,你必须处理所有消息,直到PeekMessage返回FALSE,表示没有更多消息。

下面的流程则没有问题:
> PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)返回了FALSE,表明消息队列中没有消息了。
> 一个新消息进入到消息队列。
> 调用MsgWaitForMultipleObjects并使用了QS_ALLPOSTMESSAGE标志。

MsgWaitForMultipleObjects调用确实会立即返回,因为传入的消息设置了“队列中有一条没人知道的新消息”标志,而QS_ALLPOSTMESSAGE匹配该标志,因此导致MsgWaitForMultipleObjects立即返回。


MsgWaitForMultipleObjectsEx函数允许你传递MWMO_INPUTAVAILABLE标志以指示它应该检查以前忽略的输入。

有了以上这些知识,请解释为什么使用以下代码观察到的这样的行为:
“有时我的程序卡住并且报告的记录比它应该报告得少。我必须摇动鼠标才能获得要更新的值。 又过了一会儿,它落后了两个,然后又落后了三个……”

总结

这些个老技术,虽然古老得尘封上了厚厚的灰尘,但是,如果你不能深刻理解,则你做的东西,始终无法”高出一品”。

最后

Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《MsgWaitForMultipleObjects and the queue state》