Collection was modified, enumeration operation may not execute

PATO7 picture PATO7 · Mar 29, 2012 · Viewed 25k times · Source

I have multithreads application and i get this error

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

I probably have problem with my collection, because on one thread i read my collection and on another thread i modify collection.

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


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

I am trying to lock collection with this code, but doesn't work.

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

Any ideas to fix that problem?

Answer

sll picture sll · Mar 29, 2012

This is a pretty common mistake - modifying a collection whilst iterating it using foreach, keep in mind that foreach uses readonly IEnumerator instance.

Try to loop through the collection using for() with an extra index check so if the index is out of bounds you would be able to apply additional logic to handle it. You can also use LINQ's Count() as another loop exit condition by evaluating the Count value each time if the underlying enumeration does not implement ICollection:

If Markers implements IColletion - lock on SyncRoot:

lock (Markers.SyncRoot)

Use for():

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

You might find this post useful: How do foreach loops work in C#?