Josh
Josh

Reputation: 13828

Finding how a foreach collection gets modified

How do I find out which function or target is modifying the items in a foreach loop in a multithreaded application?

I continously keep getting the error "Collection was modified; enumeration operation may not execute". I'm not removing or adding any items to the generic list within the for loop. I want to find out how it is getting modified. What is the best way to do this?

Thanks

Upvotes: 2

Views: 3119

Answers (8)

JayMcClellan
JayMcClellan

Reputation: 1611

Wait a minute - I think we've all missed the point.

The collection classes are not thread-safe. If the collection is being accessed by multiple threads without thread-locking, then you need to fix that. It's a particularly insidious problem because it will work correctly [edit - or throw a predictable exception] 99.999% of the time, and 0.001% of the time it will do something totally unpredictable and nearly impossible to reproduce.

A simple approach is to use lock{} statements around EVERY place where ANY code accesses the collection. That may be slight overkill but it is the safest plan. For iteration you can either put a lock around the whole loop or if you don't want to block out other threads that long, just lock it long enough to make a snapshot:

object[] snap;
lock (list)
{
   snap = list.ToArray();
}
foreach (object x in snap) ...

Upvotes: 7

Mike Cole
Mike Cole

Reputation: 14743

You may also try changing the class name of your collection to see where it is all referenced.

Upvotes: 0

Øyvind Skaar
Øyvind Skaar

Reputation: 1840

You might want to try out the ObservableCollection class for this. There are some examples for making this thread safe as well.

Upvotes: 0

CurtainDog
CurtainDog

Reputation: 3205

You should be able to set an exception breakpoint, then it's simply a matter of going through each thread to see which one modified the collection. In any case if the collection is shared amongst multiple threads it will need to be properly synchronised.

Upvotes: 0

Richard
Richard

Reputation: 109170

Replace the collection with an ObservableCollection, attach events to modifications and break on them in the debugger (or capture stack trace etc.).

Upvotes: 1

JayMcClellan
JayMcClellan

Reputation: 1611

This is not a direct answer, just a suggestion that might help - in a multithreaded situation where a collection might get modified during iteration, I usually use the ToArray method to create a snapshot of the list for iteration:

foreach (object x in list.ToArray()) ...

Upvotes: 2

Tommi Forsström
Tommi Forsström

Reputation: 1467

Would it be feasible to copy the contents of the global collection to a more tightly scoped variable to protect outside meddling with the data?

Upvotes: 0

John Saunders
John Saunders

Reputation: 161831

The best way to do this is to not expose the collection to many classes which could possibly change it. Make it private to one particular class, then only the methods of that class could possibly change it.

Otherwise, you would need to create a derived class from the collection class, and override all the methods that could update the collection. Set breakpoints at all the overrides.

Upvotes: 0

Related Questions