序列化时遇“集合已修改”错误,如何定位目标集合?
定位Json.NET序列化时被修改的集合
我之前也碰到过一模一样的糟心事——序列化包含大量列表和属性的大型对象时,因为某个集合在遍历(序列化)过程中被修改,直接触发了异常。分享几个我亲测有效的排查方法,尤其是适合在即时窗口里快速定位的技巧:
即时窗口专属排查命令
- 锁定检测法:在异常触发的断点处,你可以通过检测集合是否被其他线程锁定来判断是否正在被修改。在即时窗口里运行这段代码,能自动遍历
myObj里的所有集合类型属性,找出疑似被修改的目标:
原理是:如果集合正在被修改,通常会被修改线程锁定,foreach(var prop in myObj.GetType().GetProperties().Where(p => typeof(System.Collections.IEnumerable).IsAssignableFrom(p.PropertyType) && p.PropertyType != typeof(string))) { var col = prop.GetValue(myObj); if(col != null && !System.Threading.Monitor.TryEnter(col, 0)) { Console.WriteLine($"疑似被修改的集合:{prop.Name}"); } }Monitor.TryEnter会返回false。 - 版本号追踪法:像
List<T>、HashSet<T>这类.NET内置集合,内部都有一个_version私有字段——每次集合被修改(添加/删除/清空),这个数值都会递增。在即时窗口里直接查看这个值,多次执行如果数值变化,就说明这个集合在被修改:// 把YourType换成集合实际的元素类型 ((System.Collections.Generic.List<YourType>)myObj.TargetListProperty)._version
额外调试辅助技巧
- 用可视化工具实时监控:在Visual Studio调试窗口中,右键点击可疑集合,选择“可视化”→“集合可视化器”,可以实时观察集合的元素数量和内容变化,序列化过程中如果有变动一眼就能看到。
- 给集合加临时日志:在
JsonConvert.SerializeObject前后,给每个重要集合记录Count值和哈希码,如果序列化后数值和之前不一致,那这个集合就是问题所在。 - 在集合修改方法上加断点:如果是自定义集合,直接在
Add/Remove方法上设断点;如果是内置集合,可以通过Visual Studio的“断点→新建断点→函数断点”,输入System.Collections.Generic.List1.Add`来给所有List的Add方法加断点,触发时查看调用栈就能找到修改集合的线程和代码位置。
内容的提问来源于stack exchange,提问作者bdd
相关产品推荐
相关产品推荐

