严重依赖 Application.DoEvents() 的 Windows 窗体应用程序如何在无需重新设计的情况下降低其稳定性?

Posted

技术标签:

【中文标题】严重依赖 Application.DoEvents() 的 Windows 窗体应用程序如何在无需重新设计的情况下降低其稳定性?【英文标题】:How can a Windows Forms application that relies heavily on Application.DoEvents() be made less unstable without having to re-design it? 【发布时间】:2013-03-20 04:49:57 【问题描述】:

我现在负责维护的应用程序严重依赖 Application.DoEvents() 方法,虽然我没有确凿的证据证明所有突然和莫名其妙的应用程序崩溃都是由使用此方法引起的,到目前为止,我发现的大多数问题似乎都与代码执行流程围绕此方法的方式有关。

我在整个代码中看到的模式或多或少如下:

    用户触发的事件被触发

    事件处理程序运行

然后:

    产生了一个新线程

    与其阻塞 UI 线程和 UI 直到生成的线程不再运行,或者让控制离开事件处理程序,代码循环,每次调用 Application.DoEvents(),直到它收到一个指示生成的线程不再运行的信号。 (在某些情况下,派生线程在等待其他事件完成时会同时调用 Application.DoEvents()。)

    在 #2 中看到的模式在允许控制离开事件处理程序过程之前重复多次。

或:

    通过 Show() 或 ShowDialog() 方法创建并显示表单。

    与其阻塞 UI 线程和 UI 的其余部分,直到用户与 Form 交互,或者让控件离开事件处理程序,代码循环,每次调用 Application.DoEvents(),直到它接收指示用户已与表单交互的信号。

    下一个 Form 显示给用户,并重复相同的练习,直到最后允许许多 Forms 之后的控件离开事件处理程序。

我知道当您面前没有代码时很难诊断问题,但是假设对 Application.DoEvents() 的调用在某种程度上与此应用程序的不稳定行为有关,那会是什么无需从头开始重新设计即可修复此应用程序的最简单方法?

是否只是让事件处理程序生成一个新线程,允许控制权立即离开事件处理程序,然后使用 WaitHandle 阻止生成的线程而不是重复调用 Application.DoEvents()或其他一些信号机制,直到生成的线程接收到另一个线程已完成其工作或用户已与表单交互的通知?

【问题讨论】:

天哪。 '是否只是让事件处理程序产生一个新线程,允许控制立即离开事件处理程序'YES! ..或者,不要产生一个新线程,发出一个已经存在并且正在等待的信号。或者将任务提交到线程池。 随便 - 不要在 GUI 事件处理程序中等待。 BeginInvoke 线程输出回 GUI。 从轨道上发射核弹,唯一确定的方法。 【参考方案1】:

除了从线程中删除 DoEvents 的好技巧之外,您是否尝试过使用 BackgroundWorker 类?它更适合简单的线程操作和与表单的通信。 http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx http://www.dotnetperls.com/backgroundworker

【讨论】:

【参考方案2】:

您的继承设计存在多个大问题。在不使用核武器的情况下,如 Hans 所建议的那样(实际上并不是一个坏主意),首先要彻底摆脱来自非 GUI 线程的任何 Application.DoEvents() 调用。

然后开始处理其他堆肥。

【讨论】:

以上是关于严重依赖 Application.DoEvents() 的 Windows 窗体应用程序如何在无需重新设计的情况下降低其稳定性?的主要内容,如果未能解决你的问题,请参考以下文章

C#之Application.DoEvents()

什么相当于 WPF 应用程序中的 Application.DoEvents()

WPF 中的 Application.DoEvents() 在哪里?

Application.DoEvents() 在应用程序运行时不断调用?

与 Application.DoEvents() 和 PictureBox 混淆 [重复]

等待 WebBrowser 完成加载时 Application.DoEvents() 出现问题