I'm building an app in C# using Visual Studio. I'm using a ConcurrentDictionary
. I'm iterating through all the elements in that ConcurrentDictionary
, and perform an action on each element. If the action fails, I remove the element from the ConcurrentDictionary
.
I know that this is bad behavior if you do that with normal Dictionaries, Lists, etc... But is it allowed with a ConcurrentDictionary
?
So my question is: Is the below code fragment correct? More specifically, am I allowed to use TryRemove
on the ConcurrentDictionary
that I'm iterating?
foreach (var prop in _PropertyByPropId)
{
// Add the Property to the Pool. If successfully parsed, we will get a SimId not equal to -1.
int iSimId = PropertyPool.AddPropertyInPool(PNPDeviceID, prop.Value, PortName);
if (iSimId != -1)
{
// If successful, also add it to the dictionary by iSimId
if (!_PropertyBySimId.TryAdd(iSimId, prop.Value))
// In the (very unlikely) case that a Property is added twice (same iSimId), we remove the second Property
_PropertyByPropId.TryRemove(prop.Key, out _);
}
else
// If unsuccessful, remove the Property
_PropertyByPropId.TryRemove(prop.Key, out _);
}
I found an older thread removing-items-from-a-concurrentdictionary on this forum, but that seems to give answers related to the multithreading aspects of a ConcurrentDictionary
. I think my question is different?
Yes, it is perfectly valid to remove items from a
ConcurrentDictionary<K,V>
during an enumeration. All operations on this collections are thread-safe and atomic. Nevertheless, performing two atomic operations in succession does not equal to performing one combined atomic operation. It is entirely possible that the data in theConcurrentDictionary<K,V>
might become semantically corrupted, because two concurrent combined operations interfered with each other in an unexpected way. I am not in a position to judge if your specific scenario and usage, allows semantic data corruption to occur.The
ConcurrentDictionary<K,V>
collection is excellent for simple multithreading scenarios, but becomes exponentially unsuitable, a headache and a bug factory, when the scenarios become more complicated. At some point of complexity it becomes more safe and productive to go with a standardDictionary<K,V>
protected with thelock
statement, instead of trying to tame the concurrent beast.