Словарь безопасности параллельного использования

Мне нужно поточно-безопасный способ получить каждый элемент ConcurrentDictionary(строка, список)

Безопасно ли использовать следующую конструкцию?

foreach (var item in concurrentDict)
{
     var readonlyCollection = item.Value.AsReadOnly();
     //use readonly collection, (I need only Values of the concurrent dictionary)
}

Я хочу использовать значения словаря безопасности.

1 ответ

Решение

foreach с частью все в порядке, с оговоркой, что одновременно добавленные элементы могут или могут быть отмечены как включенные в итерацию. Вы не получите исключения, хотя.

Тем не менее, вы должны быть осторожны с item.Value, который имеет тип Listпотому что списки не потокобезопасны. Если другой поток изменяет список, пока вы читаете его в цикле, вы можете получить исключение.

призвание AsReadOnly() в вашем списке не поможет, потому что вы получаете обратно обертку для первоначального списка. Если чтение из исходного списка внутри обертки выбрасывает, то же самое происходит и из обертки. Более того, вы не можете исправить это, просто сделав поверхностную копию вложенного списка, поскольку одновременное изменение может быть выполнено во время создания копии.

Один подход заключается в lock список во время чтения и записи:

foreach (var item in concurrentDict) {
    List<string> listCopy;
    lock (item.Value) {
        listCopy = item.Value.ToList();
    }
     //use collection copy
}

Когда записывающий поток изменяет список внутри словаря, он должен выполнить такую ​​же блокировку:

if (concurrentDict.TryGetValue("mykey", var out list)) {
    lock (list) {
        list.Add("newValue");
    }
}
Другие вопросы по тегам