GUI跨线程操作 [英] GUI cross thread operations

查看:77
本文介绍了GUI跨线程操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有winForm项目,它有一个dataGridView,它绑定到一个从workerThread更新的dataTable。当我在workerThread上更新我的dataTable时,我使用dataGridView.BeginInvoke()。我这样做是为了处理任何交叉线程问题并防止阻塞。我还有一个winForm timerControl,每秒触发一次并对我的dataTable进行一些清理操作。



我的问题是,我的dataTable正在更新来自和来自的数据workerThread并使用timerControl清理mainThread我在这里有线程问题吗?



示例:

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

推荐答案

我不相信你将基于您的共享范围有限。一个操作是添加新记录。而另一个正在改变。你可能有一个竞争条件,其中一个枚举器错过了对某些新行的检查,但是它应该在以后拿起它,因为它是在一个计时器上。



我会建议查看算法,因为连续枚举所有行似乎效率很低。



此外,这是一个更好的方法来调用UI线程重复的代码(你可能需要调整它,因为我是通过内存来做的):



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):

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


这篇关于GUI跨线程操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆