Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update datasource of datagridview from another thread in c#

I have a backgrounder thread running along with a ui thread. Now in the backgrounder_doWork method, i have a datatable that i am adding info to from a database. I want it to bind to a datagridview in the ui thread to display to the user. So when the dataTable is updated with new info as it comes in from the database, the datagridview should automatically refresh to add/subtract any new rows of info recieved from the backgrounding thread. How can i do this? I have tried this:

private delegate void dGValueDelegate();
private void dGVValue()
{
    BindingSource bSource = new BindingSource();
    dtFailures.DataSource = bSource;
    bSource.DataSource = dt;
}

where dt is a class level variable. Inside the backgrounder_dowork method, at the beginning i call the dGVVAlue method and then after that the info gets added to the datatable in the backgrounding thread. The datagridview wont display however...

like image 218
Norman Avatar asked Jun 17 '11 15:06

Norman


2 Answers

The code below should work for you:

private delegate void SetDGVValueDelegate(BindingList<Something> items);

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{    
    // Some call to your data access layer to get dt

    SetDGVValue(DataTable dt)
}

private void SetDGVValue(DataTable dt)
{    
    if (dataGridView1.InvokeRequired)    
    {        
        dataGridView1.Invoke(new SetDGVValueDelegate(SetDGVValue), dt);    
    }    
    else    
    {        
        dataGridView1.DataSource = dt;    
    }
}

In your question you mention using BindingSource, which does not have an Invoke method - if you have a binding source you can instead Invoke on the form:

// On the form
public void SetBindingSourceDataSource(object newDataSource)
{
    if (InvokeRequired)
        Invoke(new Action<object>(SetBindingSourceDataSource), newDataSource);
    else
        this.bindingSource.DataSource = newDataSource;
}

You can also do this in a single line using Lamda expressions:

void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{    
    // Some call to your data access layer to get dt

    dataGridView1.Invoke((Action)(() => dataGridView1.DataSource = dt));
}
like image 186
David Hall Avatar answered Nov 07 '22 06:11

David Hall


Also, using the DataGridView.Invoke(Delegate) method will allow you to ensure that you are making the changes to your datagridview in the thread to which it belongs.

like image 22
therealmitchconnors Avatar answered Nov 07 '22 06:11

therealmitchconnors