Hi,
I'm having trouble locking on an item within a Collection - specifically a ConcurrentDictionary.
I need to accept a message, look up that message within the Dictionary and then run a lengthy scan on that. As the program takes a lot of memory, after the scan the objects return true if they think its a good time to delete it (which I do by removing it from the Dictionary). However, another thread could come at a similar time and try to access that same object right after the delete. This is my first attempt:
string dictionaryKey = myMessage.someValue;
DictionaryObject currentObject = myConcurrentDictionary.GetOrAdd(dictionaryKey, new DictionaryObject());
// we can be interrupted here
lock (currentObject)
{
//KeyNotFoundException is possible on line below
if (myConcurrentDictionary[dictonaryKey].scan(myMessage)) // Scans the message - returns true if the object says its OK to remove it from the dictionary
{
DictionaryObject temp; // It's OK to delete it
if (!queuedMessages.TryRemove(ric, out temp)) // Did delete work?
throw new Exception("Was unable to delete a DictionaryObject that just reported it was ok to delete it");
}
}
However, the above doesn't work - it's possible for one thread to remove an object from the Dictionary right before another is going to attempt to access that object within the Dictionary. After reading that lock is shorthand for Monitor.Enter and Monitor.Exit, I tried this:
string dictionaryKey = myMessage.someValue;
Monitor.Enter(GetDictionaryLocker);
DictionaryObject currentObject = myConcurrentDictionary.GetOrAdd(dictionaryKey, new DictionaryObject());
// we can be interrupted here
lock (currentObject)
{
Monitor.Exit(GetDictionaryLocker);
//KeyNotFoundException is still possible on line below
if (myConcurrentDictionary[dictonaryKey].scan(myMessage)) // Scans the message - returns true if the object says its OK to remove it from the dictionary
{
DictionaryObject temp; // It's OK to delete it
if (!queuedMessages.TryRemove(ric, out temp)) // Did delete work?
throw new Exception("Was unable to delete a DictionaryObject that just reported it was ok to delete it");
}
}
Both ways can result in a KeyNotFoundException when trying to look the object up within the Dictionary.
Does anyone know how I could find the object I want to lock and then lock it without being interrupted? Sorry - I'm new at concurrency and feel thoroughly confused!
Thanks,
Frederik