【问题标题】:Application.DoEvents, when it's necessary and when it's not?Application.DoEvents,什么时候需要,什么时候不需要?
【发布时间】:2017-06-23 17:22:55
【问题描述】:

使用Application.DoEvents有什么必要性,什么时候应该使用?

【问题讨论】:

    标签: doevents


    【解决方案1】:

    Application.DoEvents 通常用于确保在 UI 线程上执行一些长时间运行的操作时定期处理事件。

    更好的解决方案就是不这样做。当您需要更新 UI 时,在单独的线程上执行长时间运行的操作,编组到 UI 线程(使用 Control.BeginInvoke/InvokeBackgroundWorker)。

    Application.DoEvents 引入了重新进入的可能性,这可能导致非常难以理解的错误。

    【讨论】:

    • 乔恩,您说是为了确保定期处理事件……哪些事件?在顺序编程中,假设我们在表单上有一个按钮。当用户单击时,例如表单的不透明度发生变化......现在,除了按钮的单击之外,这里还有哪些事件?
    • 重绘、调整大小、鼠标移动等。有很多事件,即使您的应用程序代码没有明确处理其中的大部分。
    • @JonSkeet 我希望您能就DoEvents 的可能有效使用提供反馈。 stackoverflow.com/questions/45023826/…
    【解决方案2】:

    Windows 维护一个队列来保存各种事件,例如单击、调整大小、关闭等。当控件响应事件时,所有其他事件都保留在队列中。因此,如果您的应用程序处理按钮单击的时间过长,则应用程序的其余部分将显示为冻结。因此,您的应用程序在为响应事件而执行一些繁重的处理时,可能会出现无响应的情况。虽然理想情况下您应该以异步方式进行大量处理以确保 UI 不会冻结,但一个快速简单的解决方案是定期调用 Application.DoEvents() 以允许将未决事件发送到您的应用程序。

    对于好的 Windows 应用程序,最终用户不喜欢任何形式的应用程序在执行较大/重量级操作时冻结。用户总是希望应用程序以响应方式平稳运行,而不是冻结 UI。但在谷歌搜索后,我发现 Application.DoEvents() 不是一个在应用程序中更频繁使用的好习惯,因此最好使用 BackGround Worker Thread 执行长时间运行的任务而不冻结窗口。

    如果你实际看一下,你会得到更好的主意。只需复制以下代码并检查应用程序是否放置 Application.DoEvents()。

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            For i As Integer = 0 To 1000
                System.Threading.Thread.Sleep(100)
                ListBox1.Items.Add(i.ToString())
                Application.DoEvents()
            Next
        End Sub
    

    【讨论】:

      【解决方案3】:

      恕我直言,您更应该永远不要使用它,因为您最终可能会遇到非常意外的行为。 刚刚生成的代码没问题。诸如您正在再次执行您当前所在的事件处理程序之类的事情,因为用户按下了两次键等等。 如果要刷新控件以显示当前进程,则应显式调用该控件的 .Update,而不是调用 Application.DoEvents。

      【讨论】:

        猜你喜欢
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 2017-05-23
        • 1970-01-01
        • 2018-12-10
        • 2010-12-29
        • 2017-07-13
        • 2012-08-21
        相关资源
        最近更新 更多