使用后台工作者填充dataGridView。

6

我有这段代码片段:

private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        remplirDataGrid();
    }

private void frmChercherActesLoad(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();

        }



 private void remplirDataGrid()
        {
            dataGridView1.DataSource = ActeServices.getAllActes(0, 40);
            dataGridView1.Columns[0].Visible = false;
            dataGridView1.Columns[1].HeaderText = "Code acte";
            dataGridView1.Columns[2].HeaderText = "Désignation";
            dataGridView1.Columns[3].HeaderText = "Pris en charge";
            dataGridView1.Columns[4].HeaderText = "Id article";
            dataGridView1.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
        }

这里是方法getAllActe

public static IEnumerable<Acte> getAllActes(int skipCount, int takeCount)
        {
            var myTableAdapter = new SmartDocDALServices.SmartDocDataSetTableAdapters.actesTableAdapter();
            myTableAdapter.Fill(myDataSet.actes);
            var myResult = from q in myDataSet.actes.AsEnumerable()
                            select new Acte
                            {
                                code = q.code,
                                designation = q.designation,
                                priseEnCharge = q.prise_en_charge,
                                idArticle = q.id_article,
                            };

            if (skipCount != -1)
                myResult.Skip(skipCount);
            if (takeCount != -1)
                myResult.Take(takeCount);
            IEnumerable<Acte> myResultRet = myResult.ToList();
            return myResultRet;

我喜欢做的是在运行应用程序时使用后台工作器来填充我的datagridview。但是,我得到了这个错误:

跨线程操作无效:控件“dataGridView1”已经成为除其创建线程之外的线程访问的对象。


我尝试了这个方法

 private void backgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
      IEnumerable<Acte> result = ActeServices.getAllActes(0, 40);
       backgroundWorker1.ReportProgress(0, result);

    }

    void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {

      dataGridView1.DataSource = (IEnumerable<Acte>)e.UserState;
      dataGridView1.Columns[0].Visible = false;
      dataGridView1.Columns[1].HeaderText = "Code acte";
     ***

但时间没有得到回报?我希望当后台工作加载数据时,数据网格能够更新。对于每个数据加载,它将被添加到数据网格中。

4个回答

4

在后台工作线程中无法更新UI。

您需要向UI发送事件,然后执行以下操作:

private void EventHandler(object sender, YourEventArgs e)
{
    if (this.dataGridView1.InvokeRequired)
    {
        this.dataGridView1.Invoke((MethodInvoker)delegate { this.AddToGrid(e.YourData); });
    }
    else
    {
        this.AddToGrid(e.YourData);
    }
}

3

这是因为GUI元素只能在GUI线程中进行修改。要解决这个问题,您需要使用Dispatcher在GUI线程上调用更改。

DataGrid应该事先设置好,所以在异步操作中只需填充数据即可。

var data = ActeServices.getAllActes(0, 40);

Dispatcher.BeginInvoke( new Action( () => { dataGridView1.DataSource = data; }))

3

DataGridView不支持多线程操作。但是,如果数据已经可用,则设置DataSource应该足够快。

我建议:

  1. 仅使用BackgroundWorker在另一个线程中加载数据

  2. 在RunWorkerCompleted事件中设置DataSource和其他DataGridView的修改(您可以通过设置e.Result = ActeServices.getAllActes(0, 40)将DoWork方法的结果传递到Completed事件中)

  3. 可选:将dataGridView1.AutoGenerateColumns设置为false,并手动添加列,无论是在Windows Forms Designer中还是在代码中,以避免闪烁。


+1 - 当我正在输入类似的回复时,这个回复突然出现了。 - Joel Etherton

1

BackgroundWorker类旨在在后台线程上运行长时间操作。由于只允许从创建它们的线程访问UI组件,因此您可以使用BackgroundWorker类的RunWorkerCompleted事件,在DoWork处理程序完成后更新UI。此外,您可以使用BackgroundWorker类的ProgressChanged事件安全地更新进度UI。


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