集合已修改,枚举操作可能无法执行

我有multithreading应用程序,我得到这个错误

************** Exception Text ************** System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource) at System.Collections.Generic.List`1.Enumerator.MoveNextRare() at System.Collections.Generic.List`1.Enumerator.MoveNext() ... 

我的collections可能有问题,因为在一个线程上我读取了我的collections,在另一个线程上我修改了collections。

 public readonly ObservableCollectionThreadSafe Markers = new ObservableCollectionThreadSafe(); public void problem() { foreach (GMapMarker m in Markers) { ... } } 

我试图用这段代码锁定集合,但不起作用。

 public void problem() { lock(Markers) { foreach (GMapMarker m in Markers) { ... } } } 

有什么想法来解决这个问题?

这是非常常见的错误 – 在使用foreach迭代它时修改集合,请记住foreach使用只读IEnumerator实例。

使用带有额外索引检查的for()尝试循环遍历集合for()这样如果索引超出范围 – 你可以应用额外的逻辑来处理这个,也可以作为循环退出条件你可以使用LINQ Count()来评估计数值每次如果基础枚举没有实现ICollection

如果Markers实现IColletion – 锁定SyncRoot:

 lock (Markers.SyncRoot) 

for()

 for (int index = 0; index < Markers.Count(); index++) { if (Markers>= Markers.Count()) { // TODO: handle this case to avoid run time exception } } 

可能会发现这篇文章有用: foreach循环如何在C#中工作?

你需要锁定读数和写入方面。 否则其中一个线程将不知道锁定并将尝试读取/修改集合,而另一个线程正在修改/读取(分别)锁定

尝试阅读您的collections的克隆

 foreach (GMapMarker m in Markers.Copy()) { ... } 

这将创建您的集合的新副本,该副本不会受到另一个线程的影响,但在收集大量数据时可能会导致性能问题。

所以我认为如果你在阅读和编写过程中锁定集合会更好。

您可以使用foreach,但必须将集合强制转换为列表并使用点运算符来访问行为方法。

示例:Markers.Tolist()。ForEach(i => i.DeleteObject())

不完全确定你对你的collections品做了什么。 我的例子是假设您只想删除集合中的所有项目,但它可以应用于您尝试对集合执行的任何行为。

我通过使用解决了这个问题

 var data = getData(); lock(data) { return getData().Select(x => new DisplayValueModel(x)); } 

代替

 return getData().Select(x => new DisplayValueModel(x));