说说MsgWaitForMultipleObjects和队列状态
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》
相关文章
- 倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-点击运行按钮进入到运行状态报错Error starting TwinCAT System怎么办 AdsWarning1823怎么办
- tableView选中状态编辑
- HDU 2809 God of War(DP + 状态压缩)
- requests获取所有状态码
- iOS开发那些事--iOS6 UI状态保持和恢复
- 使用jstack检测Java应用的死锁(deadlock)状态
- hibernate对象的状态以及生命周期
- JavaWeb课程复习资料——Http状态 405-方法不允许
- 单元格中输入数据时,QTextEdit如何直接进入编辑状态
- 贪心算法——状态不重复,无法使用dp优化的时候就要考虑了
- 状态模式实现