I'm encountering the error:
System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
Throughout my code there are hash tables of characters, objects, etc. that constantly need to be read and removed. My code uses a foreach
loop to do something with all of the values inside the hash table, but say one character logs off as the foreach
is looping... and the hash table is modified... boom, error.
Note that any foreach
code that directly modifies the hash table are copied into lists and the parent list is edited from there, that is not the issue. The issue is the reading of hash tables that are constantly edited.
So I understand what the problem is, just not the best way to go about remedying it. Here's a simple example of code that occasionally throws a collection modified error:
foreach (Character CC in World.H_Chars.Values)
{
if (CC.MyGuild != null && CC.MyGuild.GuildName != G.GuildName
&& CC.MyGuild.Allies.ContainsValue(G.GuildName))
{
CC.MyClient.AddSend(Data); // error on this line
CC.MyClient.EndSend();
}
}
So I guess my question is, what's the best way to go through a hash table of objects that is constantly being modified?
You could try using a
System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue>
. This as a key:value pair data structure that is thread-safe (e.g. it's a generic HashTable type implementation—it has O(1) lookup of elements). It can be updated while enumerating. However, you do need to be aware that when enumerating over this type of collection you are possibly getting "dirty" reads (i.e. the collection you're iterating over is a snapshot of the dictionary at the time the iteration began—so updates that occur after you've began iterating may not be visible in the current iteration of the collection).There is also a
System.Collections.Concurrent.ConcurrentBag<T>
that is the thread-safe equivalent ofSystem.Collections.Generic.List<T>
.So I guess my question is what's the best way to go through a Hashtable of Objects that's constantly being modified?
I suspect the best way is not to. :)
Consider looking at the problem another way. For instance, I see you're looking for data with certain characteristics, that presumably result from the constant modifications to the hashtable you mentioned. Those modifications are events. If you can arrange things such as to be able to react to those events in the first place, that will solve the issue of the constantly changing hashtable where they're subsequently stored.