c# - Receiving "Error: Collection was modified; enumeration operation may not execute" in multithreaded application -



c# - Receiving "Error: Collection was modified; enumeration operation may not execute" in multithreaded application -

presently, writing application periodically drains singleton collection:

lock (_lockitemsreceivedobject) { datetime committime = datetime.now; while (itemsreceivedinstance.count > 0) { processinfo(committime); } }

here processinfo:

private void processinfo(datetime committime) { dictionary<int32, item>.enumerator enumerator = itemsreceivedinstance.getenumerator(); if (enumerator.movenext()) { item item = enumerator.current.value; // set item persistent storage , perform other processing... itemsreceivedinstance.remove(enumerator.current.key); } }

here more details on exception:

error: collection modified; enumeration operation may not execute. @ system.collections.generic.dictionary`2.enumerator.movenext()

elsewhere in programme other threads receiving items , putting them singleton itemsreceivedinstance collection. doesn't create sense me, however, since using lock, itemsreceivedinstance collection should not able modified until emptied process exits critical section, why receiving exception? have suggestions? tia.

update:

thank you, codeweed , wayne, comments. acceptable way modify collection?

{ concurrentdictionary<int32, item>.enumerator enumerator = itemsreceivedinstance.getenumerator(); if (enumerator.movenext()) { item item = enumerator.current.value; // set item persistent storage , perform other processing... var itemtoremove = enumerator.current.key; enumerator.dispose(); itemsreceivedinstance.remove(itemtoremove); } }

update 2:

thank codeweed , wayne, , else considered issue. foreach loop enumerator allows dirty reads, take snapshot of dictionary using toarray() (see http://geekswithblogs.net/blackrabbitcoder/archive/2011/02/17/c.net-little-wonders-the-concurrentdictionary.aspx), how have modified code:

datetime committime = datetime.now; foreach (keyvaluepair<int32, item> kvp in itemsreceivedinstance.toarray()) { processinfo(committime, kvp.value); } ... private static void processinfo(datetime committime, item item) { // set item persistent storage , perform other processing... }

technically may work, think it's still way contrived. why not:

datetime committime = datetime.now; foreach (var kvp in itemsreceivedinstance) { processinfo(committime, kvp); } itemsreceivedinstance.clear(); ... private static void processinfo(datetime committime, keyvaluepair<int, item> kvp) { // set item persistent storage , perform other processing... }

note subtle difference between , trying accomplish on imapct of exceptions in processinfo. if you're handling exception , don't potentially want re-process item in dictionary result, you'll want track items processed , remove dictionary, perhaps in finally block.

c# multithreading collections enumerator

Comments

Popular posts from this blog

php - Android app custom user registration and login with cookie using facebook sdk -

django - Access session in user model .save() -

php - .htaccess Multiple Rewrite Rules / Prioritizing -