使用backgroundworkers更新datagridviews后的GUI冻结

时间:2010-03-08 16:35:20

标签: user-interface datagridview backgroundworker freeze maximize

我已经制作了一个同时运行三个后勤工作者的应用程序。它基本上更新了三个datagridviews,它正在进行点击。我的问题是如果我按下maximumbox按钮或任何datagridview中的任何地方程序挂起很长一段时间。我可以使用水平滚动而不是垂直滚动。我尝试过Backgroundworker_runworkercompleted,并在线程更新了各自的datagridviews后根据需要触发。这是正常行为还是我做错了什么建议会有所帮助。 P.S:我使用step方法运行整个程序,它们在代码中没有无限循环。 提前致谢 JHON

6 个答案:

答案 0 :(得分:2)

在您致电Backgroundworker1.RunWorkerAsync()以暂时禁用数据网格滚动条之前,请放置此行代码。

DataGridView1.ScrollBars = ScrollBars.None

现在,在BackgroundWorker1_RunWorkerCompleted事件中添加以下代码行,重新启用datagridview的滚动条。

DataGridView1.ScrollBars = ScrollBars.Both

这绝不会使您的应用程序无效。

答案 1 :(得分:0)

听起来你还在以某种方式阻止UI线程。发布一些代码段可能会对您有所帮助。此外,您的进程的CPU利用率是多少?如果cpu使用率很高,你可能会以某种方式使UI线程挨饿。

答案 2 :(得分:0)

好的,我已经找到了解决问题的方法,同时按顺序消除了感知的问题点,我在backgroundworker.dowork事件之外调用了我的datagridview,并解决了问题。 故事的道德“永远不会在背景工具线之内更新数据网格视图”特别是当你不知道你做错了什么时:)。我希望将来可以帮助别人。

答案 3 :(得分:0)

您必须确保从UI线程更新datagridviews。

答案 4 :(得分:0)

我遇到了同样的问题。从UI线程更新我的dataGridViews时,它们工作正常。当我试图从backgroundWorker向他们添加一系列行时,他们没有反应。

为了纠正这个问题,我将行添加到了dataTable中。当我启动backgroundWorker时,我将dataGridView的.datasource属性设置为空。当工人完成时,我再次将其设置回dataTable。这两者都强制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

答案 5 :(得分:0)

回答@Jhon为时已晚,但似乎可以帮助其他人。 就我而言,我使用的是BindingSource,并且只有在必须显示滚动条的记录太多的情况下,UI才会冻结。

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

一个简单的例子:

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

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