Click here to Skip to main content
15,437,139 members
Please Sign up or sign in to vote.
1.00/5 (2 votes)
See more:
I have winForm project that has a dataGridView that's bound to a dataTable that's updated from a workerThread. When I update my dataTable on the workerThread I use dataGridView.BeginInvoke(). I do this to handle any cross threading issues and to prevent blocking. I also have a winForm timerControl that fires every second and does some clean operations on my dataTable.

My question is, by my dataTable being updated with data from and on the workerThread and cleaned up on the mainThread with the timerControl am I having threading issues here?

Example:
class Form1: Form
{
   MyDataCls myDatCls;
   DataGridView grid;
   DataTable dataTbl;
   Timer tmr;

   public Form1()
   {
      grid = new DataGridView();
      
      dataTbl = new DataTable();

      DataColumn col;
      col = new DataColumn();
      col.ColumnName = "Time"
      dataTbl.Columns.Add(col);

      col = new DataColumn();
      col.ColumnName = "Name"
      dataTbl.Columns.Add(col); 

      col = new DataColumn();
      col.ColumnName = "Addrs"
      dataTbl.Columns.Add(col);

      grid.DataSource = dataTbl;

      myDataCls = new MyDataCls();
      myDataCls.PushData += new PushDataEvntHndlr(myDataCls_PushData);
      
      tmr = new Timer();
      tmr += new Timer(tmr_Tick);
      tmr.Interval = 1000;
      tmr.Start();
   }

   // this is the handler I use to receive data that
   // comes from a workerThread
   private void myDataCls_PushData(string[] someData)
   {       
       if(grid.InvokeRequired)
       {
          DataRow row = dataTbl.NewRow();

          grid.BeginInvoke(new MethodInvoker(delegate()
          {
             row["Time"] = someData[0];
             row["Name"] = someData[1];
             row["Addrs"] = someData[2];
             dataTbl.Rows.Add(row);
          }));
       }
       else
       {
          row["Time"] = someData[0];
          row["Name"] = someData[1];
          row["Addrs"] = someData[2];
          dataTbl.Rows.Add(row);
       }
   }

   // this is the timer handler that does the cleanup
   private void tmr_Tick(object sender, EventArgs e)
   {
      if (dataTbl.Rows.Count > 0)
      {
         foreach (DataRow row in dataTbl.Select())
         {
             if (row["Name"] == "Joe Doe")
                 row["Name"].Delete();
         }
      }
   }
}
Posted
Updated 17-Oct-13 11:53am
v3

1 solution

I don't believe you will based on the limited scope of your sharing. The one operation is adding new records. And the other is changing. You could have a race condition where an enumerator misses a check on some of the new rows, but it should pick it up later since it's on a timer.

I would recommend looking at the algorithm, because it seems pretty inefficient to enumerate all the rows continually.

Also, here's a better way to invoke back on the UI thread that doesn't duplicate code (you may have to tweak it since I'm doing it by memory):

C#
private void myDataCls_PushData(string[] someData)
{       
    if (grid.InvokeRequired)
    {
       var pushAction = new Action<string[]>(myDataCls_PushData);
       grid.Invoke(pushAction, someData);
    }
    else
    {
       DataRow row = dataTbl.NewRow();

       row["Time"] = someData[0];
       row["Name"] = someData[1];
       row["Addrs"] = someData[2];
       dataTbl.Rows.Add(row);
    }
}
 
Share this answer
 
Comments
d.allen101 18-Oct-13 9:08am    
hey tgrt, can you please clarify for me where/how I'm at risk of a race condition?
tgrt 19-Oct-13 11:16am     CRLF
The key thing is that the DataTable is not thread-safe for write operations. That means any cross-thread write behavior is undefined. You're not performing any synchronization between your two write operations (one adding and one reading/changing). Race conditions come up in unexpected ways. The sure bet that it can happen is when you perform operations on different threads that work on the same data.
d.allen101 19-Oct-13 11:21am    
thanks for the reply/answers. but i still don't understanding why or how I'm at risk of a race condition if the dataTable is operated on the same thread. I thought I didn't have any threading issues?
tgrt 19-Oct-13 11:58am     CRLF
I didn't realize you were using the System.Windows.Forms.Timer. It executes on the UI thread. You stated in your original post "...dataTable that's updated from a workerThread", so I surmised that you were doing all of your updates from a worker thread. I would more highly recommend doing something about the inefficient looping through the rows, because of the fact it's running on the UI thread. I don't know what the overall picture of your solution is, but you could consider the events the DataTable exposes for adding and changing rows.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900