У меня проблемы с блокировкой элемента внутри Коллекции, в частности ConcurrentDictionary.
Мне нужно принять сообщение, найти это сообщение в Словаре и затем выполнить длительное сканирование по нему.Поскольку программа занимает много памяти, после проверки объекты возвращают true , если считают, что сейчас самое время удалить его (что я и делаю, удаляя его из словаря).Однако другой поток может прийти в то же время и попытаться получить доступ к этому же объекту сразу после удаления.Это моя первая попытка:
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");
}
}
Однако вышеприведенное не работает - один поток может удалить объект из Словаря, прежде чем другой попытается получить доступ к этому объекту в Словаре.,Прочитав, что блокировка является сокращением для Monitor.Enter и Monitor.Exit , я попытался сделать следующее:
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");
}
}
Оба способа могут привести к KeyNotFoundException при попыткеищите объект в Словаре.
Кто-нибудь знает, как я могу найти объект, который хочу заблокировать, и затем заблокировать его без прерывания?Извините - я новичок в параллелизме и чувствую себя сбитым с толку!
Спасибо,
Фредерик