ConcurrentDictionary и Clear () - функция. Обеспечение безопасности экспорта данных без потери данных - PullRequest
4 голосов
/ 24 января 2012

Любые идеи о том, как сделать ConcurrentDictionary потокобезопасным в условиях, когда значения экспортируются в список ex и после того, как этот словарь очищается.Так что любой другой поток не может добавить данные между экспортом и очисткой.

Примерно так: "

List<data> list;
list = (List<data>)_changedItems.Values; //get values before clearing
_changedItems.Clear();

" И добавление выполняется другими потоками с помощью функции _changedItems.AddOrUpdate

* 1007.* Теперь есть возможность потерять новые данные между извлечением данных из словаря и очисткой контента, если какой-то поток добавляет объекты данных в коллекцию перед строкой очистки.

Или это единственный способ добавить и очиститьвнутренний замок.

lock(object)
{
    List<data> list;
    list = (List<data>)_changedItems.Values;  
    _changedItems.Clear();
}

И

lock(object)
    _changedItems.AddOrUpdate

Необходима функция Clear, которая безопасно возвращает все очищенные элементы из словаря ..

-Larry

Ответы [ 2 ]

2 голосов
/ 24 января 2012

Действительно, вызов двух поточно-безопасных методов в последовательности не гарантирует атомарность самой последовательности. Вы правы, что lock для обоих вызовов, чтобы получить значения и очистить, необходимо.

0 голосов
/ 24 апреля 2012

Вы можете использовать TryRemove(key, out value) метод. Возвращает удаленный элемент. Таким образом, вам не нужно блокировать словарь для перемещения буферизованных данных.

List<data> list;
var keys = dict.Keys;
foreach(var key in keys)
{
    data value;
    dict.TryRemove(key, out value);
    list.Add(value);
}

Обновление: на самом деле вы можете выполнять итерации непосредственно по ConcurrentDictionary даже во время его изменения. Таким образом, вам не нужно собирать набор ключей из свойства .Keys, которое может быть (?) Медленным, в зависимости от реализации.

List<data> list;
foreach(var kvp in dict)
{
    data value;
    dict.TryRemove(kvp.Key, out value);
    list.Add(value);
}
...