我知道如何使用委托给主控线程上更新的控制,就像一个魅力。 我在这里的问题是,如果我加入一个大的DataSet
(比如2000项)到绑定DataGridView
,它需要5-8秒网格填充和5-8秒的整个GUI锁定期间。 我怎样才能更新DataGridView
这样它不会锁定用户界面?
需要明确的是,该问题不是我正在做一个慢查询数据库和UI阻塞上,我已经有DataSet object[]
和添加对象的阵列到BindingList<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
会造成问题。
您添加记录,而GridView控件被链接到的数据源。 这意味着它将每次更新的布局。
怎么样,你先填写您的数据源,然后才将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循环可以去到另一个线程,但我不认为你需要一个。
就像尼克说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();
}
}
考虑使用一个BackgroundWorker。 我不知道太多关于他们自己,但在谷歌一点点搜索发现,作为一个很好的可能性。