Dear Deer
Dear Deer

Reputation: 99

Adding data to DataSet from different threads and showing them in DataGridView simultaneously

I'm trying to add data to DataSet object from 3 different threads. All threads are System.Threading.Timer object threads because I'm using 3 separate timers (System.Threading.Timer type) in the program. After each TimerCallback delegate is invoked I'm acquiring data from some external PLCs (one timer for each PLC) and trying to put those data to DataSet. Acquiring data from PLCs works perfect because I'm able to display these data in some DataGridViews (one DataGridView for each PLC) There is also anotherDataGridView object (fourth) which should reflect all changes in DataSet immediately because it is bound to the DataSet. In the end these data I would like to put to database - but that's not a problem right now.

I need the data acquired from PLCs to put in the DataSet object. Also what I would like to see is watching all changes from DataSet in DataGridView right away after those changes take place.

I set the (fourth) DataGridView object properties as follows :

this.dgvxDataSet.AutoGenerateColumns = true;
this.dgvxDataSet.DataSource = DataSet1.Tables[0];

My code is as follows :

public partial class Form1 : Form
{

DataSet _ds = new DataSet("dataSet1");
System.Threading.Timer timer1;
System.Threading.Timer timer2;
System.Threading.Timer timer3;


private void Form1_Load(object sender, EventArgs e)
{
    BuildDataSet();

    this.dgvxDataSet.AutoGenerateColumns = true;
    this.dgvxDataSet.DataSource = DataSet1.Tables[0];
}

private void BuildDataSet()
{ 
    DataTable table1 = DataSet1.Tables.Add("table1");

    table1.Columns.Add("col1", typeof(Int32));
    table1.Columns.Add("col2", typeof(Int32));
    table1.Columns.Add("col3", typeof(Int32));
    table1.Columns.Add("col4", typeof(Int32));
    table1.Columns.Add("col5", typeof(DateTime));
    table1.Columns.Add("col6", typeof(Int32));
    table1.Columns.Add("col7", typeof(Int32));
}    

private void btnReadData_Click(object sender, EventArgs e)
{
    timer1 = new System.Threading.Timer(new TimerCallback(PoolingStartPLC1), null, 0, Timeout.Infinite);
    timer1.Change(0, (int)nudPollingTiming.Value);
    timer2 = new System.Threading.Timer(new TimerCallback(PoolingStartPLC2), null, 0, Timeout.Infinite);
    timer2.Change(0, (int)nudPollingTiming.Value);
    timer3 = new System.Threading.Timer(new TimerCallback(PoolingStartPLC3), null, 0, Timeout.Infinite);
    timer3.Change(0, (int)nudPollingTiming.Value);            
}

public void PoolingStartPLC1(object state)
{
    /*
     Acquireing data from PLC1 which works fine
    */

    DataRow newRow;

    //I'm adding data to DataSet through MethodInvoker() because the DataSet was created in 
    //the main thread. 
    this.Invoke(new MethodInvoker(() =>
    {
        newRow = DataSet1.Tables[0].NewRow();
        newRow["col1"] = DataSet1.Tables[0].Rows.Count + 1;
        newRow["col2"] = variable11;
        newRow["col3"] = variable12;
        newRow["col4"] = variable13;
        newRow["col5"] = dateTimeVariable1;
    }));
}

public void PoolingStartPLC2(object state)
{
    /*
     Acquireing data from PLC2 which works fine
    */

    DataRow newRow;

    //I'm adding data to DataSet through MethodInvoker() because the DataSet was created in 
    //the main thread. 
    this.Invoke(new MethodInvoker(() =>
    {
        newRow = DataSet1.Tables[0].NewRow();
        newRow["col1"] = DataSet1.Tables[0].Rows.Count + 1;
        newRow["col2"] = variable21;
        newRow["col3"] = variable22;
        newRow["col4"] = variable23;
        newRow["col5"] = dateTimeVariable2;
    }));
}

public void PoolingStartPLC3(object state)
{
    /*
     Acquireing data from PLC3 which works fine
    */

    DataRow newRow;

    //I'm adding data to DataSet through MethodInvoker() because the DataSet was created in 
    //the main thread. 
    this.Invoke(new MethodInvoker(() =>
    {
        newRow = DataSet1.Tables[0].NewRow();
        newRow["col1"] = DataSet1.Tables[0].Rows.Count + 1;
        newRow["col2"] = variable31;
        newRow["col3"] = variable32;
        newRow["col4"] = variable33;
        newRow["col5"] = dateTimeVariable3;
    }));
}


}

After a while the data should be in the DataSet object but the problem is they are not. During debugging I see empty DataSet and the DataGridView ofcourse doesn't display any rows ...

I don't know what am i doing wrong. Interestingly I don't receive any concurrency exceptions associated with adding data to the same DataSet object from 3 separate threads simultaneously. Maby I should use some locks or something (if any). If yes - I don't know how and where ... But the worst is that I don't know how put the data (which I have) to DataSet.

I'm using VS2010 Ultimate. The project is Windows forms project.

Thanks

Upvotes: 2

Views: 728

Answers (1)

Eric Scherrer
Eric Scherrer

Reputation: 3408

You have to add the row to the DataSet. One would think that .NewRow() adds the row but it doesn't - it just creates a new row that fits that DataSet table. Call DataSet1.Tables[0].Rows.Add(newRow). That should work.

Upvotes: 2

Related Questions