C#: 如何从后台线程访问 datagridview1

3

我正在尝试从后台工作线程访问主线程上的UI控件。我知道这是一个众所周知的问题,但我找不到任何关于如何从后台线程特别访问DataGridView的信息。我知道创建ListBox的代码是:

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个回答

2
DataGridViewInvoke 方法与 ListBox 相同。以下是一个示例,其中 DataGridView 最初绑定到一个 BindingList<items>,我们创建了一个新列表并将其绑定到该列表。这应该等价于您从 Oracle 调用中获取 DataTable 并将其设置为 DataSource 的要求。请保留 HTML 标签。
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事件处理程序中转换参数对象:
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!               
}

我不想使用RunWorkerCompleted,因为我的DataGrid代码在Backgrounder的中间。我的Backgrounder线程实际上调用另一个方法,该方法希望输出到DataGridView。我真的不明白你在做什么?我想调用委托方法并传递要显示在GridView中的信息。我不认为你的方法可以做到这一点。 - hWorld
@Dominique - 我的方法更新了DataGridView,但是有很多种方法可以实现这个功能,如果没有更多信息,我无法给您一个匹配您需求的示例。如果您不是在后台线程中工作,您能否编辑您的问题代码? - David Hall
@Dominique - 你可以使用绑定源并调用其上的invoke方法来实现这一点。 - David Hall
在后台线程中,我只是读取Oracle数据库,将其存储在DataTable中,并尝试将其传递给DataGridView的DefaultGridView方法以显示它。我需要一种在后台线程中将DataTable传递给DataGridView的方法。 - hWorld
@Dominique,你想做的就是更新数据源吗?我已经修改了我的示例来实现这个。 - David Hall

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接