从不同的线程向DataSet添加数据并同时在DataGridView中显示它们

时间:2014-06-13 12:39:04

标签: c# multithreading datagridview timer dataset

我试图从3个不同的线程向DataSet对象添加数据。所有线程都是System.Threading.Timer个对象线程,因为我在程序中使用了3个独立的定时器(System.Threading.Timer类型)。在调用每个TimerCallback委托之后,我从一些外部PLC(每个PLC一个计时器)获取数据并尝试将这些数据放入DataSet。从PLC获取数据非常有效,因为我能够在某些数据中显示这些数据 DataGridViews(每个PLC一个DataGridView)还有另一个DataGridView对象(第四个),它应该立即反映DataSet中的所有更改,因为它绑定到DataSet。最后,我想将这些数据放到数据库中 - 但这不是现在的问题。

我需要从PLC获取的数据放入DataSet对象。此外,我希望看到在发生这些更改后立即DataSet DataGridView查看所有更改。

我按如下方式设置(第四个)DataGridView个对象属性:

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

我的代码如下:

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


}

一段时间后,数据应该在DataSet对象中,但问题是它们不是。在调试过程中,我看到空DataSet,而DataGridView的课程没有显示任何行......

我不知道自己做错了什么。有趣的是,我没有收到任何与同时从3个独立线程向同一个DataSet对象添加数据相关的并发异常。 Maby我应该使用一些锁或其他东西(如果有的话)。如果是的话 - 我不知道如何以及在哪里......但最糟糕的是,我不知道如何将数据(我拥有的)放到DataSet

我正在使用VS2010 Ultimate。该项目是Windows表单项目。

由于

1 个答案:

答案 0 :(得分:2)

您必须将行添加到DataSet。有人会认为.NewRow()添加了行但它没有 - 它只是创建一个适合该DataSet表的新行。调用DataSet1.Tables [0] .Rows.Add(newRow)。这应该有用。