下面的伪代码是程序的大概,错误原因是因为线程b修改数据源时正巧碰到用户操作控件引发的,系统实际有多个线程操作这个datagridview和数据源。
线程a
{
  DataViewdv = new DataView(db);
  dv.RowFilter = "delete = false"
  this.datagridview.DataSource= dv;
}线程b(5秒执行一次)
{
  foreach(var r in db.rows)
  {
    if(r["tm"] < DateTime.Now) r["delete"] = true;  }
}
当我正在操作datagridview的时候,比如对这个datagridview进行双击、拖动滚动条、编辑单元格文本,这时正好遇到了线程b执行,突然datagridview数据源有所减少或者全部消失,这时崩溃,错误定位到Main()方法中,错误提示是“在 System.NullReferenceException 中第一次偶然出现的“System.Windows.Forms.dll”类型的异常”,用try也不能捕获异常,跟找不到确切的文字。请问如何解决多线程操作datagridview会出现系统崩溃的问题?

解决方案 »

  1.   

    没看明白,楼主为什么要同时多线程操作同一个datagrid呢?
      

  2.   

    这种情况应该做线程同步,一个线程操作的时候,另一个线程就不能操作,用lock等锁定
      

  3.   

    在线程B中禁止datagridview双击、拖动滚动条、编辑单元格文
      

  4.   


    //线程a
    {
    lock()
    {
      DataViewdv = new DataView(db);
      dv.RowFilter = "delete = false"
      this.datagridview.DataSource= dv;
    }
    }//线程b(5秒执行一次)
    {
    lock()
    {
      foreach(var r in db.rows)
      {
        if(r["tm"] < DateTime.Now) r["delete"] = true;
    }
    }
      

  5.   

    把对 datagridview 操作的部分加锁就可以了
      

  6.   

    要通过lock锁定
    http://www.cnblogs.com/chenxizhang/archive/2008/09/09/1287421.html
      

  7.   

    用lock锁,限定线程B的执行时间间隔,这样可以防止资源冲突
      

  8.   


    是的,如果楼主对这方面不太熟悉的话,建议你使用线程池,比如backgroundworker什么的,可以省去很多麻烦
      

  9.   

    有答案了,
    现在发现.NET版的,有答案也很久不结贴的。RP啊。
      

  10.   

    这就是资源冲突问题,要解决最好加lock
      

  11.   


    请问这里的lock()不锁任何对象吗?
      

  12.   

    很抱歉我没有说明白,其实线程a只运行一次,程b每隔5秒运行一次。
    现在的主要问题是,即使是加入了锁,但当线程b运行修改数据源的同时,datagridview上显示的数据条数也有变化,如果这个时候正在对datagridview进行操作,就会引起系统崩溃。
      

  13.   


    如何禁止这些操作?在线程b运行前后我加入了 datagridview.enabled=false,虽然可以减少崩溃的次数,但还不能彻底解决问题。
      

  14.   

    我也碰到过 不过出现次数不是很频繁
    试试在b线程 Monitor.Enter(dv)看看 不过记得在trycatch里释放 否则可能死锁
      

  15.   

    代码里貌似并没有通过线程访问控件 而是访问了dataview 
    帮lz顶 
      

  16.   


      this.datagridview.DataSource= dv;
    这句就在访问了把
      DataViewdv = new DataView(db);
      dv.RowFilter = "delete = false"
      this.datagridview.DataSource= dv
    做成一个委托方法
      

  17.   

            delegate void SetDataSouce();        void DoSetDataSouce()
            {
                DataView dv = new DataView(db);
                dv.RowFilter = "delete = false";
                this.datagridview.DataSource = dv;
            }        void Thread_a()
            {
                SetDataSouce PDoSetDataSouce = new SetDataSouce(DoSetDataSouce);
                PDoSetDataSouce(); 
            }        void Thread_b()
            {
               // ...
            }
      

  18.   

    更正下,上面有个地方写错了
    delegate void SetDataSouce();        void DoSetDataSouce()
            {
                DataView dv = new DataView(/*db*/);
                dv.RowFilter = "delete = false";
                this.datagridview.DataSource = dv;
            }        void Thread_a()
            {
                SetDataSouce PDoSetDataSouce = new SetDataSouce(DoSetDataSouce);
                if (datagridview.InvokeRequired)
                    datagridview.Invoke(PDoSetDataSouce, null);
                else
                    DoSetDataSouce(); 
            }        void Thread_b()
            {
               // ...
            }
      

  19.   

    改用BindingSource代替DataView了,BindingSource有俩个方法 BindingSourceSSXX.SuspendBinding(), BindingSourceJJXX.ResumeBinding(),加上更新数据时禁用DataGridView,暂时还没测出问题
      

  20.   

    http://stackoverflow.com/questions/667571/optimize-updates-to-datatable-bound-to-datagridview