从BackGroundWorker更新DataGrid

时间:2010-03-24 05:20:03

标签: c# .net winforms backgroundworker

我在c#应用程序中有一个后台工作器和一个DataGrid。在我的Backgroundworker的工作中,它将调用我的dll中的Api,它将在SQLite数据库中输入一些数据。完成我的Api调用后,我会报告我的Backgroundworker的进度和进行中事件,我从Db获取内容并将其作为DataSource分配给我的网格。我在同一个背景工作者中调用相同的API。在处理我的应用程序崩溃的过程中。但是,如果我不在ProgressChanged中分配dataSource,我的应用程序不会崩溃。

3 个答案:

答案 0 :(得分:4)

我假设您必须使用Invoke方法访问UI对象。

如果没有尝试使用以下方法(在拥有控件的底层窗口句柄的线程上执行指定的委托,使用指定的参数列表。):


 //In Form.Designer.cs

 Label myLabel = new Label();


 //In code behind under Background worker method
 LabelVlaueSetter SetLabelTextDel = SetLabelText; 
 if (myLabel .InvokeRequired)
 {

   myLabel.Invoke(SetLabelTextDel, "Some Value");
 }

 private delegate void LabelVlaueSetter(string value);

 //Set method invoked by background thread
 private void SetLabelText(string value)
 {
   myLabel.Text = value;
 }



答案 1 :(得分:2)

正如Johnathan Allen所提到的,这应该不重要。除非发生其他事情。我有两种情况,我无法与BackgroundWorker生成的事件中的某些控件进行交互。唯一有效的方法是使用Invoke方法。

尝试在创建DataSource控件的同一线程上分配DataGridView。您可以通过控件的Invoke方法执行此操作。使用以下代码。 (我没有测试过,但这是标准模式。)

如果这不起作用,请尝试Jonathan Allen的建议。

实际上,无论哪种建议最容易先尝试。


    private delegate void SetDataSourceDelegate(object value);

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
        DataTable oData = null; //'assign data source
        if (dataGridView1.InvokeRequired) {
            dataGridView1.Invoke(new SetDataSourceDelegate(SetDataSource), new Object[] {oData});
        }else{
            SetDataSource(oData); 
        }
    }

    private void SetDataSource(object value) {
        dataGridView1.DataSource = value;
    }

答案 2 :(得分:1)

应该没关系,但为什么使用ProgressChanged而不是RunWorkerCompleted?

此外,尝试在没有BackgroundWorker的情况下在GUI线程上执行所有操作。如果您的代码中存在问题或代码与GUI交互的方式,那将告诉您。