11

我有多线程应用程序,我收到此错误

************** 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()
   ...

我的收藏可能有问题,因为在一个线程上我阅读了我的收藏,而在另一个线程上我修改了收藏。

public readonly ObservableCollectionThreadSafe<GMapMarker> Markers = new ObservableCollectionThreadSafe<GMapMarker>();


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

我正在尝试使用此代码锁定集合,但不起作用。

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

有什么想法可以解决这个问题吗?

4

6 回答 6

14

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

尝试使用for()额外的索引检查循环遍历集合,因此如果索引超出范围,您将能够应用额外的逻辑来处理它。如果基础枚举未实现,您还可以通过每次Count()评估值来使用 LINQ 作为另一个循环退出条件:CountICollection

如果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# 中工作?

于 2012-03-29T12:17:41.887 回答
4

尝试阅读您收藏的克隆

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

这将创建一个不会受另一个线程影响的集合的新副本,但在大量集合的情况下可能会导致性能问题。

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

于 2012-03-29T12:17:37.127 回答
4

您需要在阅读和写作方面都锁定。否则,其中一个线程将不知道锁并将尝试读取/修改集合,而另一个线程则在持有锁的情况下(分别)修改/读取

于 2012-03-29T12:16:36.763 回答
-1

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

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

代替

return getData().Select(x => new DisplayValueModel(x));
于 2018-06-22T07:39:38.337 回答
-1

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

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

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

于 2017-10-18T19:36:06.690 回答
-1

这对我有用。对标记执行 ToList() 操作: foreach (GMapMarker m in Markers.ToList())

于 2021-12-22T16:05:39.667 回答