views:

46

answers:

6

Hi I have this code sinnpet

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);
        }

/// and here is the method 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;

What I like to do is to fill my datagridview usign the background worker once I run the application I got this error

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

any help?

A: 

You can't update the UI from a BackgroundWorker thread.

You need to send an event to the UI and then have something like:

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);
    }
}
ChrisF
A: 

It is because GUI stuff cannot be modified from other threads than the GUI thread. To fix this, you need to invoke the changes on the GUI thread by using the Dispatcher.

The DataGrid should be setup beforehand, so all you do in your async operation is fill the data.

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

Dispatcher.BeginInvoke( new Action( () => { dataGridView1.DataSource = data; }))
hkon
+2  A: 

The DataGridView is not thread safe. However, setting the DataSource if the data is already available should be fast enough.

I would recommend:

  1. Only use your BackgroundWorker to load the data in another thread

  2. Set the DataSource and the other modifications of the datagridview in the RunWorkerCompleted Event (you can pass the result from the DoWork method to the Completed event by setting

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

  3. Optional: Set dataGridView1.AutoGenerateColumns to false and manually add the columns either in the Windows Forms Designer or in code to avoid flicker.

SchlaWiener
+1 - I was in the middle of typing a similar response when this one popped up.
Joel Etherton
A: 

The BackgroundWorker class was designed to run a long-standing operation on a background thread. Since you are only allowed to access UI components from the thread that created them, you can use the RunWorkerCompleted event of the BackgroundWorker class to update your UI once your DoWork handler has completed. Also, you can safely update a progress UI using the ProgressChanged event of the BackgroundWorker class.

Alan
A: 

So I have to retrive data in the Dowork and the affect them to the datagrid? or I Have to work with the progress methode?

For this sort of thing you should edit your question or comment on the relevant answer.
ChrisF
A: 

I try this

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

but nothing gained in time?. I'd like that the datagrid update when the BGW loads data foreash data load it add it to the DGV

You should edit your question to add this additional information rather than posting an answer.
ChrisF