【问题标题】:Clean messages in Windows Message Pump在 Windows 消息泵中清除消息
【发布时间】:2015-01-25 20:18:48
【问题描述】:
  1. 我对 Windows 消息泵了解不多,但我猜事件是使用消息泵触发的。

当我的 Web 浏览器控件导航到某些网站时,它会触发各种文档完成事件。一旦我在 WebBrowser_Document_Completed() 中获得了我需要的东西,我想忽略所有进一步的文档完成。

  1. 怎么办?

如果我在 Document_Completed(...) 中显示 MessageBox(),它会显示多条消息盒子,看起来它是在并行线程中运行的,但是当我调试它时,我发现它总是在主线程上运行。

  1. 其他两个线程是什么时候创建的?

此外,当我按下关闭时,它会关闭窗口,但进程仍在后台运行。我没有使用任何其他线程,但我在调试时仍然看到其他两个线程。

【问题讨论】:

  • 一拿到第一个事件,可以退订该事件,还是使用一个标志忽略该事件?顺便说一句,您是如何得出有多个线程的结论的?
  • @SriramSakthivel 如果没有返回对话框结果,程序不会走得更远,如果它在同一个线程上运行,那么如何同时显示多个消息框,我是如何得出结论的
  • 重入会导致这种情况,所以技术上单线程可以做到这一点。在消息框中显示Thread.CurrentThread.ManagedThreadId 以确认它们确实是不同的线程。
  • 在等待MessageBox.Show 或其他模式时,winforms 将在内部调度消息队列并处理消息,最终队列中的某些消息导致同一主线程再次调用DocumentCompleted 事件(即使您仍在 MessageBox.Show 上)。重入有点像递归,但不同的是你没有自己调用方法而不是递归(你故意调用它)。同Application.DoEvents
  • MessageBox 很危险,它本身会泵送一个消息循环,因此允许这种重新进入。 DocumentCompleted 事件可以再次触发,为您提供另一个消息框。这使它成为调试代码的一种非常痛苦的方式,只需使用调试器断点或 Debug.WriteLine()。

标签: c# multithreading winforms webbrowser-control message-pump


【解决方案1】:

最直接的方法是通过覆盖它的 WndProc() 方法来拦截和评估正在传播到您的控件的消息。通过一点调试器观察,您可以识别与目标事件对应的 wm_message 常量,然后相应地更改执行流程。在 MSDN 网站上有一个很好的例子: https://msdn.microsoft.com/en-us/library/system.windows.forms.control.wndproc%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

要了解您正在查看/查找的消息,请参考: http://www.pinvoke.net/default.aspx/Constants/WM.html

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多