DataTable保存到文件时触发Collection was modified异常如何解决?
异常触发原因
你没有手动写foreach不代表相关逻辑不存在,该异常是DataTable.WriteXml()方法内部触发的:
Collection was modified; enumeration operation might not execute.
WriteXml序列化DataTable的过程中,会内部遍历DataTable的行、列等集合完成数据导出,而DataTable本身不支持读写并发操作:如果你的后台写文件线程执行序列化的同时,有其他业务线程正在修改这个DataTable(比如新增/删除行、修改单元格内容、调整列结构等),就会打断内部的枚举遍历逻辑,抛出这个异常。
解决方案
- 加全局锁保护所有读写操作
定义一个公共锁对象,所有修改该DataTable的业务逻辑、以及调用WriteXml的逻辑都要包裹在同一把锁的lock代码块中,保证同一时间只有一个线程操作DataTable,从根源上避免并发冲突。示例代码:// 定义全局锁对象 private readonly object _dataTableLock = new object(); // 所有修改DataTable的位置都加锁 lock(_dataTableLock) { // 新增/删除行、修改单元格等操作 } // 写文件的位置也加锁 lock(_dataTableLock) { dt.WriteXml(outputFilePath + "users.xml"); } - 序列化前创建DataTable快照
调用WriteXml之前先通过Copy()方法生成当前DataTable状态的独立副本,用副本完成序列化操作。该方案不需要修改原有DataTable的修改逻辑,业务侵入性更低,适合DataTable数据量不大、并发修改频率不高的场景。示例代码:// 创建快照后用副本写文件 var dtSnapshot = dt.Copy(); dtSnapshot.WriteXml(outputFilePath + "users.xml"); - 替换非线程安全的DataTable:如果业务允许调整存储结构,可以改用线程安全的自定义数据容器存储数据,从底层避免并发问题,不过该方案改造成本相对更高。
内容的提问来源于stack exchange,提问作者IllSkillz
相关产品推荐
相关产品推荐

