为什么通过菜单项的单击事件打开的模式对话框会处理所有窗口消息?
因此,在过去的一天左右的时间里,我一直在修复由模式对话框引起的错误。 我正在开发一个通过 Windows 消息泵与服务器通信的应用程序。 当我使用 ShowDialog() 显示模式表单时,消息泵被阻止,并且我的任何消息都不会被处理,但它们确实会在队列中堆积(预期行为)。
但是,我最近注意到,如果通过菜单项的单击事件打开模式表单,则消息将被泵送到主表单并进行处理。 有谁知道为什么当通过菜单项的单击事件显示模式表单时这些消息不会被阻止?
编辑:我应该注意到我正在使用 C#。 这个怎么样; 如果没有人可以回答这个问题,谁能告诉我如何自己调查这个问题? 我唯一能想到的就是查看调用堆栈。 不幸的是,这还没有告诉我任何事情。
So for the past day or so I have been fixing a bug that is caused by a modal dialog. I work on an application which communicates with the server through the Windows message pump. When I use ShowDialog() to show a modal form, the message pump is blocked and none of my messages are processed, yet they do build up in the queue (expected behavior).
However, I recently noticed that if a modal form is opened through a menu item's click event, the messages are pumped to the main form and processed. Does anyone know why these messages are not blocked when a modal form is shown through a menu item's click event?
EDIT: I should have noted that I am using C#.
How about this; if no one can answer this question, can anyone tell me how to investigate this myself? The only thing that I can think of would be to look at the call stack. Unfortunately, this has not told me anything yet.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
是的,我从菜单项的单击事件中调用 ShowDialog() 。 在这种情况下,消息通过模式对话框传送到主窗体。
Yes, I am calling ShowDialog() from the menu item's click event. In this case, the messages are pumped through the modal dialog to the main form.
尝试为菜单中的对话框与显示预期消息泵送行为的对话框设置相同的所有者/父级。
Try setting the same Owner/Parent for the dialog from the menu to the dialog that is showing expected message pumping behavior.
一般来说,您的客户端 UI 不应阻塞长时间的服务器操作。 .Net 使得使用BackgroundWorker 线程非常容易完成服务器工作。 请参阅这篇文章的示例:多线程导入
示例是用 VB 编写的,但您可以点击 C# 示例的链接。
In general, your client UI should not block for long server operations. .Net makes it very easy to do server work using a BackgroundWorker thread. See this post for an example: Multi Threaded Import
The example is in VB but you can follow the links for a C# example.
您是从单击事件还是其他方式调用 ShowDialog() ?
Are you calling ShowDialog() from the click event, or some other way?
您使用哪种菜单控件? 它是否可以在与主窗体运行的线程不同的线程上运行?
What kind of menu control are you using? Could it be running on a separate thread from the one where the main form is running?
@Chris:我只是使用标准的 MenuStrip 控件。 如果它在单独的线程上运行,那么我会对它如何将表单显示为模式感兴趣。 我尝试从单独的线程显示对话框,以免阻塞消息队列,但我无法将主窗体指定为父窗体,因此它不是真正的模式。
@Chris: I am just using the standard MenuStrip control. If it were running on a separate thread, I would then be interested in how it shows the form as modal. I experimented with showing the dialog from a separate thread as to not block the message queue, but I cannot specify the main form as a parent, so it is not really modal.
我不清楚你所说的“消息泵被阻止”是什么意思。
发生的情况是 ShowDialog 没有返回,因此顶级消息泵正在等待您的应用程序从处理使其调用 ShowDialog 的任何事件中返回; 这与你的处理程序正在磨削 CPU 没有什么不同。 所以,是的,从这个意义上说,消息泵被阻塞了。
但是模式对话框本身运行自己的消息泵循环,直到对话框关闭,它应该像主循环一样处理消息,所以我不明白为什么应该在队列中建立任何消息。
该消息循环处理所有窗口的消息,因为它必须允许应用程序的其他窗口正确绘制自己。
您可以尝试查看回调堆栈(从 ShowDialog 调用向下到堆栈的根)并比较“事情按预期工作”和“事情不工作”时的外观。 这可能是一些微妙的事情,比如您是否通过消息调度或消息预处理进行 ShowDialog 调用(我刚刚发现,当您调用 ContextMenuStrip.Show 时,这会有所不同)
I'm unclear at to what you mean by "the message pump is blocked".
What happens is that the ShowDialog does not return so the top-level message pump is waiting for your app to return from processing whatever event made it call ShowDialog; this is no different than if your handler for this even were grinding CPU. So, yes, in that sense, the message pump is blocked.
But the modal dialog itself runs its own message pump loop until the dialog is closed, which should process messages just as the main loop does, so I don't understand why any messages should be building up in the queue.
This message loop processes messages for all windows because it must e.g. allow other windows of the app to paint themselves properly.
You might try looking at the callback stack (from the ShowDialog call down to the root of the stack) and compare how it looks when "things are working as they should" and when "things aren't working". It may be something subtle like whether you got to the ShowDialog call through message dispatching or message preprocessing (which I have just found makes a difference when you call ContextMenuStrip.Show)