zl程序教程

您现在的位置是:首页 >  云平台

当前栏目

AfxMessageBox为什么不阻塞消息响应函数?

消息 为什么 阻塞
2023-09-11 14:16:45 时间

AfxMessageBox为什么不阻塞消息响应函数
我写了一个MFC程序,有个GUI主线程和另外一个次线程,次线程会不停向GUI线程发送我自己定义的消息。

我在消息处理函数中用了AfxMessageBox。
如下:
LRESULT CMainFrame::OnReceiveUserMessage(WPARAM w, LPARAM l)
{
  ......//代码部分1
  AfxMessageBox(_T("..."));
  ......//代码部分2
}
由于次线程会不停地向GUI线程发送此消息。
所以GUI线程会调用消息响应函数。
但让我感到困惑的是:我的第一次响应函数执行时,AfxMessageBox的消息框弹出来,我没有关闭它,意味着此消息响应函数还没有执行完(代码部分2并没有被执行)。但GUI线程的消息响应并没有停止,它在收到此线程的消息后,会陆续地进行第2次消息响应,第3次消息响应,等等,很多个消息框都会陆续地弹出来。
我的理解是,消息响应函数是在GUI线程中执行的,如果一次的消息响应没有完成,GUI线程应该等待它的返回,而不能进行消息响应,但这里为什么可以呢?

另外一个问题,如果将AfxMessageBox(_T("..."));换成一段计算代码。比如
for (int i=0; i<10000000;i+++)
{
  int k = 0;
  k++;
}
这段代码执行的时间足够长,次线程在这段时间又往主线程发送了若干消息,主线程能否在这段代码执行的时候响应后面的次线程发送来的消息,应该是不能吧?

我个人觉得这是AfxMessageBox这个函数的问题,它也许和一般的计算代码不一样。
希望和大家讨论一下,再思考一下,将AfxMessageBox换成一个模态对话框,又会怎么样呢?比如
CUserDefineDlg dlg;
dlg.Domodal();
1.
AfxMessageBox自己有一个消息循环,也就是说,OnReceiveUserMessage是可以被重入的。
如果你要挂起线程,你可以用WaitForSingleObject,但是不建议这么做。
1.
那只能说明AfxMessageBox是阻塞了,只是OnReceiveUserMessage 这个地方的处理可能并不是UI线程处理的

MFC里面UI线程有派生其他线程去处理其他事情的功能,很多控件都可以,像进度条,之所以能够连续的显示进度的变化,是因为主界面没有重绘的情况下在收到WM_PAINT的时候产生另外的线程去更新进度条部分做重绘而已.
1.
AfxMessageBox自己有一个消息循环,模态对话框也一样。
如果他们接收到不属于自己的消息,如父窗口的消息,就会转发给父,应该调用父的WindowProc处理该消息。
如果使用模态对话框替换掉AfxMessageBox,会出现同样的情况。
1.
AfxMessageBox和耗时的计算是有区别的,AfxMessageBox等待用户输入的同时在处理GUI消息,耗时的计算是没有的。
1.
消息响应函数是可以重入的,这个要注意。另外,你在工作线程中肯定用的是SendMessage,SendMessage对消息的处理跟其它的队列消息有些不同,它的优先级比较高,只要主线程处于空闲状态,Send过来的消息会被优先处理,就像直接调用消息响应函数一样。
1.
你这个LRESULT CMainFrame::OnReceiveUserMessage(WPARAM w,LPARAM l)是否重新实现过?
AfxMessageBox 如果不能阻塞基本上就一个原因拉,就是他自己的消息循环并没有阻塞,
虽然已经show出来的但没成功进入阻塞.
导致这个原因很可能是你的消息处理循环是你自己另外实现过了,而且没有放到主线程内
你是否用的是一个不带消息循环的线程去做这个过程,而且AfxMessageBox的父消息循环继承自这个没消息队列的线程?
导致了GetMessage()这个涵数永远都能不断返回,阻塞不了
1.
从你上面的描述来看,AfxMessageBox和模态对话框是肯定不能阻塞所有消息响应的,特别是自定义消息。

另外,如果是多线程环境,AfxMessageBox和模态对话框后面的代码可能在它们没有被关闭,也就是返回的情况下执行。(这个想来有点怕怕)

总之一句话,用AfxMessageBox和模态对话框多加小心就是了。
1.
也许这个对你有帮助:在google上搜索“深入探讨MFC消息循环和消息泵”
1.
“还有一事也让我晕菜: 
我在调试这个程序的过程中,在GUI线程的消息响应函数中加了一个断点,当程序运行到断点时,次线程也不运行了。我没有在GUI线程和次线程之间设置任何同步,互斥,次线程只负责将消息投递到GUI线程中。为什么GUI线程的断点会让次线程也不运行呢,按理说次线程还是应该继续向GUI线程投递消息,但它就是不工作。"