Reputation: 95
Let's assume that we have two threads and a collection:
ConcurrentDictionary<int, object[]> lists = new ConcurrentDictionary<int, object[]>();
1) One thread processes elements in collection and then remove elements from collection
foreach(object[] elem in lists.Values)
{
//do somethind
lists.TryRemove(key, out vals);
}
2) Second thread add elements to collection and then it need to be able to check elements status:
lists.Add(10, some_object);
...
if(lists.ContainsKey(10))
{
//How can I be sure that at this moment element is still exists ?
//Thread may be preempted after if() {} and second thread
//can remove object from collection
}
Upvotes: 5
Views: 525
Reputation: 102793
You are meant to use TryGetValue
, as this makes sure the check/get is atomic:
object[] val;
if(lists.TryGetValue(10, out val)) {
// Here you have a reference to the object[], even if it has subsequently been removed
}
Of course, the thread-safety of the object[]
itself is another question, which can't be solved by ConcurrentDictionary
. (For example, if say both threads modify the objects somehow, and the objects are not thread-safe, then you would need to use a lock inside the TryGetValue
block.)
Upvotes: 7
Reputation: 55760
In that case you will need to write your own locking around the code that accesses the dictionary. And at that point a concurrent dictionary is not necessarily needed anymore because you would be synchronizing access to it outside the dictionary so essentially duplicating the efforts.
// in thread 1
lock(COMMON_LOCK_OBJECT)
{
foreach(object[] elem in lists.Values)
{
//do somethind
lists.TryRemove(key, out vals);
}
}
An in thread 2:
lock(COMMON_LOCK_OBJECT)
{
lists.Add(10, some_object);
...
if(lists.ContainsKey(10))
{
}
}
Upvotes: 0