2010-06-27 5 views
4

У меня есть этот код:Заливка DataGridView спасибо, чтобы BackgroundWorker

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 помощью фона рабочего раз Я запускаю приложение. Я получил эту ошибку:

Inter-thread operation not valid: Control 'dataGridView1 has been the subject of an access from a thread other than the one it was created.


Я не попробовать этого

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"; 
    *** 

, но ничего, полученного во время ?. Мне бы хотелось, чтобы обновление datagrid, когда BGW загружает данные для загрузки данных foreash, добавляет их в DGV

ответ

3

Вы не можете обновить пользовательский интерфейс из потока BackgroundWorker.

Вам необходимо отправить событие пользовательского интерфейса, а затем что-то вроде:

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 нить. Чтобы исправить это, вам нужно вызвать изменения в потоке графического интерфейса с помощью диспетчера.

DataGrid должен быть установлен заранее, поэтому все, что вы делаете в своей операции async, заполняет данные.

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

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

DataGridView не является потокобезопасным. Однако установка DataSource, если данные уже доступны, должна быть достаточно быстрой.

Я бы рекомендовал:

  1. использовать только ваш BackgroundWorker, чтобы загрузить данные в другом потоке

  2. Установите DataSource и другие модификации DataGridView в RunWorkerCompleted Event (вы можете пройти результатом метода DoWork к заполненному случае путем установки

    e.Result = ActeServices.getAllActes (0, 40);

  3. Необязательно: установите dataGridView1.AutoGenerateColumns на false и вручную добавьте столбцы в Windows Forms Designer или в код, чтобы избежать мерцания.

+0

+1 - Я был в середине ввода аналогичного ответа, когда этот выскочил. –

0

Класс BackgroundWorker был разработан для выполнения многолетней работы на фоновом потоке. Поскольку вам разрешен доступ к компонентам пользовательского интерфейса из потока, который их создал, вы можете использовать событие RunWorkerCompleted класса BackgroundWorker для обновления вашего пользовательского интерфейса после завершения обработчика DoWork. Кроме того, вы можете безопасно обновлять пользовательский интерфейс прогресса, используя событие ProgressChanged класса BackgroundWorker.

Смежные вопросы