【发布时间】:2015-01-25 20:18:48
【问题描述】:
- 我对 Windows 消息泵了解不多,但我猜事件是使用消息泵触发的。
当我的 Web 浏览器控件导航到某些网站时,它会触发各种文档完成事件。一旦我在 WebBrowser_Document_Completed() 中获得了我需要的东西,我想忽略所有进一步的文档完成。
- 怎么办?
如果我在 Document_Completed(...) 中显示 MessageBox(),它会显示多条消息盒子,看起来它是在并行线程中运行的,但是当我调试它时,我发现它总是在主线程上运行。
- 其他两个线程是什么时候创建的?
此外,当我按下关闭时,它会关闭窗口,但进程仍在后台运行。我没有使用任何其他线程,但我在调试时仍然看到其他两个线程。
【问题讨论】:
-
一拿到第一个事件,可以退订该事件,还是使用一个标志忽略该事件?顺便说一句,您是如何得出有多个线程的结论的?
-
@SriramSakthivel 如果没有返回对话框结果,程序不会走得更远,如果它在同一个线程上运行,那么如何同时显示多个消息框,我是如何得出结论的
-
重入会导致这种情况,所以技术上单线程可以做到这一点。在消息框中显示
Thread.CurrentThread.ManagedThreadId以确认它们确实是不同的线程。 -
在等待
MessageBox.Show或其他模式时,winforms 将在内部调度消息队列并处理消息,最终队列中的某些消息导致同一主线程再次调用DocumentCompleted事件(即使您仍在 MessageBox.Show 上)。重入有点像递归,但不同的是你没有自己调用方法而不是递归(你故意调用它)。同Application.DoEvents -
MessageBox 很危险,它本身会泵送一个消息循环,因此允许这种重新进入。 DocumentCompleted 事件可以再次触发,为您提供另一个消息框。这使它成为调试代码的一种非常痛苦的方式,只需使用调试器断点或 Debug.WriteLine()。
标签: c# multithreading winforms webbrowser-control message-pump