求助,多线程操作 datagridview出现错误

zhmvb 2009-03-31 06:48:40
下面的伪代码是程序的大概,错误原因是因为线程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会出现系统崩溃的问题?


...全文
696 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
norsd 2011-12-18
  • 打赏
  • 举报
回复
http://stackoverflow.com/questions/667571/optimize-updates-to-datatable-bound-to-datagridview
wartim 2009-04-01
  • 打赏
  • 举报
回复
在线程里访问控件,要用委托来同步
EsMo 2009-04-01
  • 打赏
  • 举报
回复
我也碰到过 不过出现次数不是很频繁
试试在b线程 Monitor.Enter(dv)看看 不过记得在trycatch里释放 否则可能死锁
zhmvb 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 zzxap 的回复:]
在线程B中禁止datagridview双击、拖动滚动条、编辑单元格文
[/Quote]

如何禁止这些操作?在线程b运行前后我加入了 datagridview.enabled=false,虽然可以减少崩溃的次数,但还不能彻底解决问题。
zhmvb 2009-04-01
  • 打赏
  • 举报
回复
很抱歉我没有说明白,其实线程a只运行一次,程b每隔5秒运行一次。
现在的主要问题是,即使是加入了锁,但当线程b运行修改数据源的同时,datagridview上显示的数据条数也有变化,如果这个时候正在对datagridview进行操作,就会引起系统崩溃。

zhmvb 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 baiyunyinv 的回复:]
C# code//线程a{lock()
{
DataViewdv=newDataView(db);
dv.RowFilter="delete = false"this.datagridview.DataSource=dv;
}
}//线程b(5秒执行一次){lock()
{foreach(var rindb.rows)
{if(r["tm"]<DateTime.Now) r["delete"]=true;
}
}
[/Quote]

请问这里的lock()不锁任何对象吗?
jinsuo_1986 2009-04-01
  • 打赏
  • 举报
回复
这就是资源冲突问题,要解决最好加lock
josephSC 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 much0726 的回复:]
有答案了,
现在发现.NET版的,有答案也很久不结贴的。RP啊。
[/Quote]
??什么答案啊??贴出来共享下~
much0726 2009-04-01
  • 打赏
  • 举报
回复
有答案了,
现在发现.NET版的,有答案也很久不结贴的。RP啊。
jlj84237485 2009-04-01
  • 打赏
  • 举报
回复
帮顶一下
josephSC 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 oyljerry 的回复:]
这种情况应该做线程同步,一个线程操作的时候,另一个线程就不能操作,用lock等锁定
[/Quote]

是的,如果楼主对这方面不太熟悉的话,建议你使用线程池,比如backgroundworker什么的,可以省去很多麻烦
zhmvb 2009-04-01
  • 打赏
  • 举报
回复
改用BindingSource代替DataView了,BindingSource有俩个方法 BindingSourceSSXX.SuspendBinding(), BindingSourceJJXX.ResumeBinding(),加上更新数据时禁用DataGridView,暂时还没测出问题
wartim 2009-04-01
  • 打赏
  • 举报
回复
更正下,上面有个地方写错了
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()
{
// ...
}

wartim 2009-04-01
  • 打赏
  • 举报
回复
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()
{
// ...
}

a260881071 2009-04-01
  • 打赏
  • 举报
回复
拿分走人
wartim 2009-04-01
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 showyoumymercy 的回复:]
代码里貌似并没有通过线程访问控件 而是访问了dataview
帮lz顶
[/Quote]

this.datagridview.DataSource= dv;
这句就在访问了


DataViewdv = new DataView(db);
dv.RowFilter = "delete = false"
this.datagridview.DataSource= dv
做成一个委托方法
EsMo 2009-04-01
  • 打赏
  • 举报
回复
代码里貌似并没有通过线程访问控件 而是访问了dataview
帮lz顶
英雄在线 2009-03-31
  • 打赏
  • 举报
回复
用lock锁,限定线程B的执行时间间隔,这样可以防止资源冲突
gui0605 2009-03-31
  • 打赏
  • 举报
回复
参考楼上试试
wuyq11 2009-03-31
  • 打赏
  • 举报
回复
加载更多回复(6)

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧