频繁刷新DataGridView的DataSource会报错
来源:互联网 发布:十大杀人狂魔电影 知乎 编辑:程序博客网 时间:2024/04/28 00:32
在winform开发中,我们常常会用DataGridView来展现datatable的数据,单次或者不频繁的异步设置其DataSource属性不会有任何问题,但是如果实时的异步刷新其数据,不管你是通过异步的调用方式还是采用直接修改数据源,都会导致DataGridView报莫名其妙的错误。
比如下面的应用场景,我们需要一个客户端来显示当前CTI服务器的电话排队情况,这种数据是很实时的。针对这种应用场景,我们有一下几种实现方法,但均会不定期报错
其一:
直接设置DataGridView的DataSource属性,然后直接在监听线程里面修改数据源,模拟程序如下
public Form1() { InitializeComponent(); source = new DataTable(); source.Columns.Add("CA"); source.Columns.Add("CB"); source.Columns.Add("CC"); } DataTable source = null; Thread thmain = null; bool run = true; private void Form1_Load(object sender, EventArgs e) { dataGridView1.DataSource = source; } private void button1_Click(object sender, EventArgs e) { thmain = new Thread(new ThreadStart(main)); thmain.Start(); } private void main() { while (run) { Thread.Sleep(500); if (source.Rows.Count >= 10) { source.Rows.Clear(); } DataRow dr = source.NewRow(); dr["CA"] = "A-" + DateTime.Now.ToFileTime(); dr["CB"] = "B-" + DateTime.Now.ToFileTime(); dr["CC"] = "C-" + DateTime.Now.ToFileTime(); source.Rows.Add(dr); } } private void button2_Click(object sender, EventArgs e) { run = false; }此方法会导致GV报如下的错误:
其二:
仍然直接设置datasource属性,但是是通过异步invoke的方式实现
this.Invoke(new UpdateUI(delegate(object o){ gvPhoneList.DataSource = phoneList;}), "");通过在线程中使用invoke的方式来设置datasource属性,但仍然会报如下的错误:
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 System.Windows.Forms.DataGridViewLinkCell.PaintPrivate(Graphics g, Rectangle clipBounds, Rectangle cellBounds, Int32 rowIndex, DataGridViewElementStates cellState, Object formattedValue, String errorText, DataGridViewCellStyle cellStyle, DataGridViewAdvancedBorderStyle advancedBorderStyle, DataGridViewPaintParts paintParts, Boolean computeContentBounds, Boolean computeErrorIconBounds, Boolean paint)
在 System.Windows.Forms.DataGridViewLinkCell.GetContentBounds(Graphics graphics, DataGridViewCellStyle cellStyle, Int32 rowIndex)
在 System.Windows.Forms.DataGridViewCell.GetContentBounds(Int32 rowIndex)
在 System.Windows.Forms.DataGridViewLinkCell.MouseMoveUnsharesRow(DataGridViewCellMouseEventArgs e)
在 System.Windows.Forms.DataGridView.OnCellMouseMove(DataGridViewCellMouseEventArgs e)
在 System.Windows.Forms.DataGridView.UpdateMouseEnteredCell(HitTestInfo hti, MouseEventArgs e)
在 System.Windows.Forms.DataGridView.OnMouseMove(MouseEventArgs e)
在 System.Windows.Forms.Control.WmMouseMove(Message& m)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.DataGridView.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
后来在CSDN上找到了另外的一种方法,但是仍然会有错,只是错误的消息不一样了而已:
System.NullReferenceException: 未将对象引用设置到对象的实例。
在 System.Data.DataView.GetRecord(Int32 recordIndex)
在 System.Data.DataView.GetRow(Int32 index)
在 System.Data.DataView.System.Collections.IList.get_Item(Int32 recordIndex)
在 System.Windows.Forms.CurrencyManager.get_Item(Int32 index)
在 System.Windows.Forms.DataGridView.DataGridViewDataConnection.GetError(Int32 boundColumnIndex, Int32 columnIndex, Int32 rowIndex)
在 System.Windows.Forms.DataGridViewCell.GetErrorText(Int32 rowIndex)
在 System.Windows.Forms.DataGridViewLinkCell.GetErrorIconBounds(Graphics graphics, DataGridViewCellStyle cellStyle, Int32 rowIndex)
在 System.Windows.Forms.DataGridViewCell.GetErrorIconBounds(Int32 rowIndex)
在 System.Windows.Forms.DataGridViewCell.UpdateCurrentMouseLocation(DataGridViewCellMouseEventArgs e)
在 System.Windows.Forms.DataGridViewCell.OnMouseMoveInternal(DataGridViewCellMouseEventArgs e)
在 System.Windows.Forms.DataGridView.OnCellMouseMove(DataGridViewCellMouseEventArgs e)
在 System.Windows.Forms.DataGridView.UpdateMouseEnteredCell(HitTestInfo hti, MouseEventArgs e)
在 System.Windows.Forms.DataGridView.OnMouseMove(MouseEventArgs e)
在 System.Windows.Forms.Control.WmMouseMove(Message& m)
在 System.Windows.Forms.Control.WndProc(Message& m)
在 System.Windows.Forms.DataGridView.WndProc(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
在 System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
最后,我们尝试换一种方法来绑定数据:即手动设置数据
this.BeginInvoke(new System.Action(() => { gvPhoneList.Rows.Clear(); foreach (DataRow dr in phoneList.Rows) { gvPhoneList.Rows.Add(dr["NUMBER"], dr["ADDAT"]); } }));至此,风平浪静,没有在出错了。
猜测通过DataSource属性设置数据源的时候可能起内部实现可能需要过多的处理,导致在最开始设置给DataSource的对象(取到了某些属性)在最终绑定的时候不一致,导致报错。因此通过手动添加行的方式可以避免掉此类问题!
基于上面的猜测,采用下面的方式来处理DataSource仍然可以解决问题。
this.Invoke(new Action(() => { dataGridView1.DataSource = source.Copy(); }));至于详细的原因需要分析datagridview的绑定原理了!
- 频繁刷新DataGridView的DataSource会报错
- 频繁绑定DataGridView的DataSource却不正常显示
- list<T>作为datagridview的datasource
- DataGridView DataSource INotifyPropertyChanged 避免闪烁的方法
- 关于datagridView的刷新
- 会报错的,是什么原因?
- 一个频繁刷新内容的textview
- DataGridView Datasource Datatable
- C++: DataGridView::DataSource
- datagridview 按钮刷新的问题:
- 浅谈DataTable、DataSet与DataView,DataGridView,DataSource之间的联系
- DataGridView DataSource 如何实现排序
- CPaintDC频繁刷新 闪动
- 解决DataGridview刷新慢的办法
- 解决DataGridview刷新慢的办法
- Winforms: DataGridView的显示刷新问题
- Winforms: DataGridView的显示刷新问题
- Winforms: DataGridView的显示刷新问题
- WINCE下从data abort 找到崩溃的代码
- OpenMP中数据属性相关子句详解(2):shared/default/copyin/copyprivate子句的使用
- u-boot-2011.06在基于s3c2440开发板的移植之硬件ECC
- Android系统多媒体数据库MediaStore
- mysql的1067错误
- 频繁刷新DataGridView的DataSource会报错
- 重构初体验
- OpenMP中数据属性相关子句详解(1):private/firstprivate/lastprivate/threadprivate之间的比较
- CMOS密码清除方法
- freemark在tomcat重启问题
- Windows下MySQL5.5修改数据路径并解决1067错误
- DS8100存储系统安装配置之个人总作篇
- Linux字符设备编程(五)之struct class
- A common clock framework (from LWN)