在DataGridView中的CellEndEdit事件中删除当前行报错
写在前面,老婆问我一个UI的问题。我开始以为很简单,后来弄了一下,发觉挺难。找了不少资料才解决。在这个过程中学到不少东西,记录下来,以便以后复习。
症状
===========
在DataGridView中的CellEndEdit事件中删除当前行报错,信息如下:
Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore function
分析
===========
想要在一个控件的事件中删除掉控件本身,这个恐怕就是问题的根本原因了。我的第一感觉还是挺准的,可惜技术基础不扎实,没能贯彻下去。我最开始想:如果在这个事件处理函数中做不到,那老子再起一个线程,活生生等你这个事件执行结束了之后,再回来把你干掉总可以了吧。谁知又遇到了非创建控件的线程访问控件报exception的问题。
已经是半夜十二点多了,头已经有点昏了。没关系,脑子不好使,有google。
找到了如下的经典解决方案。
//事件处理函数 //不直接删掉该行,而是将要删掉的行存入数组,待另起的线程处理 private void m_dataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e) { PushDelIndex(e.RowIndex); Thread delTh = new Thread(new ThreadStart(delRowThread)); delTh.Start(); } private int[] delIndex = null;//待删行号的数组 private bool delFlag = true;//是否要不间断尝试删除数组中的行 private bool deling = false;//是否有线程正在执行删除操作的锁变量 private void PushDelIndex(int _index) { if(delIndex==null) { delIndex=new int[]{_index}; } else { Array.Resize(ref delIndex,delIndex.Length+1);//展示如何扩充数组 delIndex[delIndex.Length - 1] = _index; } } void delRowThread() { while (delFlag) { if (delIndex != null) { if (deling == false) { delRow(); } } Thread.Sleep(100); } } //此处展现了如何在非创建控件的线程里去修改控件的方法 private delegate void delRowCallBack(); void delRow() { if (PlayList.InvokeRequired) { deling = true; delRowCallBack o = new delRowCallBack(delRow); this.Invoke(o); } else { for (int i = 0; i < delIndex.Length; i++) { PlayList.Rows.RemoveAt(delIndex[i]); } deling = false; delIndex = null; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律