C#:从后台程序线程访问datagridview1

时间:2011-06-15 19:37:50

标签: c# datagridview multithreading

我试图从后台工作线程访问主线程上的ui控件。我知道这是一个众所周知的问题,但我找不到任何有关如何访问datagridview的信息,特别是从后台程序线程。我知道列表框的代码是:

private delegate void AddListBoxItemDelegate(object item);

private void AddListBoxItem(object item)
{
    //Check to see if the control is on another thread
    if (this.listBox1.InvokeRequired)
        this.listBox1.Invoke(new AddListBoxItemDelegate(this.AddListBoxItem), item);
    else
        this.listBox1.Items.Add(item);
}

如何使datagridview控件工作?此外,上述方法仅适用于一个列表框(listBox1),有没有办法使一个方法适用于主ui中的所有列表框控件?

由于

1 个答案:

答案 0 :(得分:1)

Invoke上的DataGridView方法的工作方式与ListBox相同。

以下是DataGridView最初绑定到BindingList<items>的示例,我们创建一个新列表并绑定到该列表。这应该等同于您从调用Oracle获取DataTable并将其设置为DataSource的要求。

private delegate void SetDGVValueDelegate(BindingList<Something> items);

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    // Some call to your data access infrastructure that returns the list of itmes
    // or in your case a datatable goes here, in my code I just create it in memory.
    BindingList<Something> items = new BindingList<Something>();
    items.Add(new Something() { Name = "does" });
    items.Add(new Something() { Name = "this" });
    items.Add(new Something() { Name = "work?" });

    SetDGVValue(BindingList<Something> items)
}

private void SetDGVValue(BindingList<Something> items)
{
    if (dataGridView1.InvokeRequired)
    {
        dataGridView1.Invoke(new SetDGVValueDelegate(SetDGVValue), items);
    }
    else
    {
        dataGridView1.DataSource = items;
    }
}

在我成功使用DataGridView的测试代码中,将该数据源设置为DoWork事件处理程序中生成的数据源。

您也可以使用RunWorkerCompleted回调,因为它被编组到UI线程。一个例子如下:

backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);

void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    dataGridView1[0, 0].Value = "Will this work?";
}

关于问题的第二部分,有几种方法可以实现这一目标。最明显的是在调用BackGroundWork时传入你想要处理的ListBox,如下所示:

backgroundWorker1.RunWorkerAsync(this.listBox2);

然后你可以在DoWork事件处理程序中强制转换arguments对象:

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    ListBox l = e.Argument as ListBox;

    // And now l is whichever listbox you passed in 
    // be careful to call invoke on it though, since you still have thread issues!               
}