1

我了解如何使用委托来更新主控制线程上的控件,就像一个魅力。我的问题是,如果我将一个大的DataSet(比如 2000 个项目)添加到一个 boundDataGridView中,填充网格需要 5-8 秒,并且在这 5-8 秒内整个 GUI 被锁定。如何更新DataGridView它以使其不锁定用户界面?

需要明确的是,问题不在于我正在对数据库进行慢速查询并且 UI 阻塞了它,我已经有了DataSet object[]并将对象数组添加到绑定到的 aBindingList<object>中:DataGrid

BindingList<object> dataProvider = new BindingList<object>();
DataGridView gridView = new DataGridView();
gridView.DataSource = dataProvider;

// ...stuff happens...

object[] source = dataSet; //of 2000 items
foreach (object item in source) {  //this foreach blocks
    dataProvider.Add(item);
}

我尝试了各种事情(我知道不会工作,但我想我会看到),比如创建一个执行 的委托dataProvider.Add(),但这并不重要,因为它仍然必须在控制线程上发生。

一些好的建议围绕着构建第BindingList一个然后设置gridView.DataSource. 虽然这有效(它会立即更新网格),但我看到添加更多数据的唯一方法是创建另一个新BindingList的,做一个gridView.DataSource.copyTo()(获取现有数据)并在其上添加新数据,然后gridView.DataSource将新的BindingList。这对我不起作用,因为我列表中的对象不是静态的,它们每个都将数据异步上传到服务器,并将它们复制到新的BindingList会导致问题。

4

3 回答 3

3

就像尼克说BackgroundWorker的可能是你最好的选择。

这是一个非常简单的例子

public partial class Form1 : Form
{
    BackgroundWorker b = new BackgroundWorker();

    public Form1()
    {
        InitializeComponent();
        b.RunWorkerCompleted += new RunWorkerCompletedEventHandler(b_RunWorkerCompleted);
        b.DoWork += new DoWorkEventHandler(b_DoWork);
    }

    void b_DoWork(object sender, DoWorkEventArgs e)
    {
        // build dataset here and assigning it to results
        e.Result = dataset;            
    }

    void b_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        // assign the dataset you built in DoWork in the gridview and update it
        dataGridView1.DataSource = e.Result;
        dataGridView1.Update();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        b.RunWorkerAsync();
    }
}
于 2009-08-18T20:58:26.640 回答
1

当 GridView 链接到 DataSource 时,您正在添加记录。这意味着它将每次更新布局。

你先填充你的 DataSource 然后再设置 DataSource 属性怎么样?

gridView.DataSource = null;
...stuff happens...

object[] source = dataSet; //of 2000 items
foreach (object item in source) {  //this foreach blocks
    dataProvider.Add(item);
}

gridView.DataSource = dataProvider;

foreach 循环可以转到另一个线程,但我认为您不需要它。

于 2009-08-18T20:40:06.147 回答
0

研究使用BackgroundWorker。我自己对它们了解不多,但在谷歌上稍作搜索表明这是一个很好的可能性。

于 2009-08-18T20:39:42.120 回答