Ваша проблема в том, что вы находитесь в параллельном коде, что означает, что несколько потоков кода могут работать одновременно.Таким образом, вы должны убедиться, что одновременные операции атомарные , т. Е. Что операция всегда выполняется как один шаг в многопоточной среде, и другой поток не может ее прервать.
код ...
if (DictionaryDomainACLStatus.ContainsKey(domainStatus))
{
return DictionaryDomainACLStatus[domainStatus];
}
... явно не атомарный, потому что состоит из двух отдельных шагов.Между ContainsKey
и индексатором другой поток может изменить словарь, что приводит к вашему KeyNotFoundException
, если модификация является Remove
.
Первой мыслью, которая приходит на ум, будет замена этих двух шагов.by ...
if (DictionaryDomainACLStatus.TryGetValue(domainStatus, out string value)) {
return value;
}
Это не поможет, хотя TryGetValue
само по себе не является атомарным, что означает, что оно может быть прервано другим потоком внутри.
Распространенное решениек этой проблеме относится введение критической секции с lock
:
lock (myCriticalSection) {
if (DictionaryDomainACLStatus.ContainsKey(domainStatus))
{
return DictionaryDomainACLStatus[domainStatus];
}
}
Любой доступ к словарю должен быть выполнен в пределах lock
той же критическойsection.
Другой вариант - использовать ConcurrentDictionary
, который обеспечивает атомарные операции.Это будет работать только в том случае, если все доступы к словарю могут быть выполнены за один (атомарный) шаг.Вот почему обычно вам будет лучше с замком.