MsgWaitForMultipleObjects 后遗症 与解决办法
来源:互联网 发布:tensorflow 自己的算法 编辑:程序博客网 时间:2024/04/28 01:38
在 调用SendMessage 产生死锁的问题分析 之后,我在界面程序中不再使用 WaitForSingleObject 了,而改用如下的函数
DWORD WaitObjectAndMsg(HANDLE hEventThread, DWORD dwMilliseconds){BOOL bWait = TRUE;DWORD dwEvt = 0;while(bWait) {DWORD dwEvt = ::MsgWaitForMultipleObjects(1 , &hEventThread, FALSE, dwMilliseconds, QS_ALLINPUT);switch (dwEvt) {case WAIT_OBJECT_0: {return WAIT_OBJECT_0;}break;case WAIT_OBJECT_0 + 1: {MSG msg;while ( ::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {if( WM_CLOSE == msg.message || WM_QUIT == msg.message ) {return WAIT_FAILED;break;} else {PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);::TranslateMessage(&msg); ::DispatchMessage(&msg); }} break;} default: {return dwEvt;break;} } }return dwEvt;}
这个函数看起来不错,在等待一个 Object 的同时,还可以边等待,边处理消息
今天才发现,这样处理有缺陷
如果在等待一个Object 时,哪怕只有 0.00001 秒,这里如果一个不小心处理了消息
那么 很自然会走到这个语句 ::DispatchMessage(&msg);
经过调试发现, ::DispatchMessage(&msg); 是阻塞的,
如果在处理消息的函数里,调用了一个
CDialog dlg;
dlg.DoModal(); 这里也是阻塞的, 如果这个窗口一直不关闭,
即使这时候 Object 已经响应了,但这个函数仍然不返回,,,,,,,因为它在双重的消息处理中。。。。。。。
下面是可参考解决办法
One danger oftheMsgWaitForMultipleObjects
functionis calling it when there are already messages waiting to be processed, becauseMsgWaitForMultipleObjects
returns only when there is a new event in the queue.In other words, consider the following scenario:
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
returnsTRUE
indicating that there is a message.- Instead of processing the message, you ignore it and call
MsgWaitForMultipleObjects
.
This wait will not return immediately, even though there is a message in the queue. That's because the call toPeekMessage
told you that a message was ready, and you willfully ignored it. TheMsgWaitForMultipleObjects
message tells you only when there are new messages; any message that you already knew about doesn't count.
A common variation on this is the following:
MsgWaitForMultipleObjects
returns that there is a message.- You call
PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)
and process that message. - You call
MsgWaitForMultipleObjects
to wait for more messages.
If it so happens that there were two messages in your queue, theMsgWaitForMultipleObjects
does not return immediately, because there are no new messages; there is an old message you willfully ignored, however.
When MsgWaitForMultipleObjects
tells you that there is a message in your message queue, you have to processallof the messages untilPeekMessage
returnsFALSE
, indicating that there are no more messages.
Note, however, that this sequence is not a problem:
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)
returnsFALSE
indicating that there is no message.- A message is posted into your queue.
- You call
MsgWaitForMultipleObjects
and include theQS_ALLPOSTMESSAGE
flag.
This wait does return immediately, because the incoming posted message sets the "There is a new message in the queue that nobody knows about" flag, whichQS_ALLPOSTMESSAGE
matches and therefore causesMsgWaitForMultipleObjects
to return immediately.
TheMsgWaitForMultipleObjectsEx
functionlets you pass theMWMO_INPUTAVAILABLE
flag to indicate that it should check for previously-ignored input.
Armed with this knowledge, explain why the observed behavior with the following code is "Sometimes my program gets stuck and reports one fewer record than it should. I have to jiggle the mouse to get the value to update. After a while longer, it falls two behind, then three..."
// Assume that there is a worker thread that processes records and// posts a WM_NEWRECORD message for each new record.BOOL WaitForNRecords(HANDLE h, UINT cRecordsExpected){ MSG msg; UINT cRecords = 0; while (true) { switch (MsgWaitForMultipleObjects(1, &h, FALSE, INFINITE, QS_ALLINPUT)) { case WAIT_OBJECT_0: DoSomethingWith(h); // event has been signalled break; case WAIT_OBJECT_1: // we have a message - peek and dispatch it if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } if (SendMessage(hwndNotify, WM_GETRECORDCOUNT, 0, 0) >= cRecordsExpected) { return TRUE; // we got enough records } break; default: return FALSE; // unexpected failure } }}
- MsgWaitForMultipleObjects 后遗症 与解决办法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObjects与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- WaitForMultipleObject与MsgWaitForMultipleObjects用法
- MsgWaitForMultipleObjects
- MsgWaitForMultipleObjects
- MsgWaitForMultipleObjects
- MsgWaitForMultipleObjects
- MsgWaitForMultipleObjects
- MsgWaitForMultipleObjects
- WaitForMultipleObject与MsgWaitForMultipleObjects的用法
- WaitForMultipleObject与MsgWaitForMultipleObjects的用法
- [转]WaitForMultipleObject与MsgWaitForMultipleObjects用法
- python模块之hashlib
- linux inotify研究4
- codeforces 215E 数位DP
- python的import路径问题
- 推荐一系列优秀的Android开发源码
- MsgWaitForMultipleObjects 后遗症 与解决办法
- shell脚本Here documents使用注意点(顶格)
- ASP.NET MVC3 jQuery Autocomplete
- 十问PHP程序员
- 软件工程考研 选什么方向比较好
- POJ--3760 魔兽世界(修订版)
- JS实现打开本地文件或文件夹
- web.xml 通过contextConfigLocation配置spring 的方式
- 一个农民工学习LINUX内核的艰辛历程/嵌入式的感受