【问题标题】:GUI freezing after datagridviews have been updated using backgroundworkers使用后台工作程序更新数据网格视图后的 GUI 冻结
【发布时间】:2010-03-08 16:35:20
【问题描述】:

我制作了一个同时运行三个后台工作程序的应用程序。它基本上更新了它正在执行的三个数据网格视图。我的问题是,如果我按下最大化框按钮或任何 datagridview 中的任何位置,程序会挂起很长时间。我可以使用水平滚动,但不能使用垂直滚动。我已经尝试过 Backgroundworker_runworkercompleted 并在线程更新了各自的数据网格视图后根据需要触发。这是正常行为还是我做错了什么任何建议都会有所帮助。 P.S:我已经使用 step 方法运行了整个程序,它们在代码中没有无限循环。 提前致谢 乔恩

【问题讨论】:

    标签: user-interface datagridview backgroundworker freeze maximize


    【解决方案1】:

    在您调用 Backgroundworker1.RunWorkerAsync() 之前放置这行代码以暂时禁用您的 datagridview 滚动条。

    DataGridView1.ScrollBars = ScrollBars.None
    

    现在通过在 BackgroundWorker1_RunWorkerCompleted 事件中添加这行代码来重新启用 datagridview 的滚动条。

    DataGridView1.ScrollBars = ScrollBars.Both
    

    这永远不会使您的应用程序无响应。

    【讨论】:

      【解决方案2】:

      听起来您仍在以某种方式阻塞 UI 线程。发布一些代码 sn-ps 可能会对您有所帮助。另外,您的进程的 CPU 利用率是多少?如果 CPU 使用率很高,您可能会以某种方式使 UI 线程处于饥饿状态。

      【讨论】:

        【解决方案3】:

        好的,我已经找到了问题的解决方案,在逐步消除感知到的问题点的同时,我在 backgroundworker.dowork 事件之外调用了我的 datagridview,瞧,解决了问题。 故事的寓意“永远不要从背景工作线程内更新数据网格视图”,特别是当您不知道自己做错了什么时:)。我希望它会在将来对某人有所帮助。

        【讨论】:

        • 您能告诉我们为什么我们不能从 backgroundworker.Dowork 更新 datagridview 的原因吗?我也面临同样的问题,所以我将 datagridview 滚动条设置为无,当 datagridview 完全更新时,我再次在 backgroundworker.runworkercompleted 事件中将滚动条设置为两者。
        【解决方案4】:

        您必须确保从 UI 线程更新数据网格视图。

        【讨论】:

          【解决方案5】:

          我遇到了同样的问题。当我的 dataGridViews 从 UI 线程更新时,它们运行良好。当我尝试从 backgroundWorker 向它们添加一系列行时,它们变得没有响应。

          为了纠正这个问题,我将行添加到数据表中。当我启动 backgroundWorker 时,我将 dataGridView 的 .datasource 属性设置为空。工人完成后,我再次将其设置回数据表。这既迫使 dataGridView 自我更新,又切断了工作线程中发生的事情与 UI 中显示的内容之间的同步连接,这似乎缓解了工作人员完成时的无响应。

          示例用法:

          Private Sub button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn1.Click
              If bgWorker1.IsBusy <> True Then
                  dataGridView1.DataSource = Nothing
          
                  bgWorker1.RunWorkerAsync()
              End If
          End Sub
          
          Private Sub bgWorker_DoWork(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles bgWorker1.DoWork
              dataTable1.Rows.Add("data")
          End Sub
          
          Private Sub bgWorker_RunWorkerCompleted(ByVal sender As System.Object, ByVal e As RunWorkerCompletedEventArgs) Handles bgWorker1.RunWorkerCompleted
              dataGridView1.DataSource = dataTable1
              dataGridView1.Refresh()
          End Sub
          

          【讨论】:

            【解决方案6】:

            回复@Jhon 为时已晚,但似乎它可能对其他人有所帮助。 就我而言,我使用的是 BindingSource,并且 UI 仅在必须出现滚动条的记录太多时才会冻结。

            当您使用后台工作者、任务或线程来完成工作时,您必须在主 UI 线程上更新您的 UI 控件。 为此,您可以调用相应线程中的方法。

            一个简单的例子:

            myDataGridView.Invoke((MethodInvoker)delegate { myBindingSource.DataSource = myData; });
            

            但我更喜欢这个解决方案: InvokeIfRequired

            【讨论】:

              猜你喜欢
              • 2022-01-11
              • 1970-01-01
              • 1970-01-01
              • 2014-08-14
              • 2010-12-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2019-05-11
              相关资源
              最近更新 更多