Обновление полей значений в ConcurrentDictionary

Я пытаюсь обновить записи в ConcurrentDictionary что-то вроде этого:

class Class1
{
    public int Counter { get; set; }
}

class Test
{
    private ConcurrentDictionary dict =
        new ConcurrentDictionary();

    public void TestIt()
    {
        foreach (var foo in dict)
        {
            foo.Value.Counter = foo.Value.Counter + 1; // Simplified example
        }
    }
}

По существу я должен выполнить итерации по словарю и обновить поле на каждом Значении. Я понимаю из документации, что должен избегать использования свойства Value. Вместо этого я думаю, что должен использовать TryUpdate за исключением того, что я не хочу заменять свой целый объект. Вместо этого я хочу обновить поле на объекте.

После чтения этой записи в блоге на блоге команды PFX: Возможно, я должен использовать AddOrUpdate и просто ни в чем не выполнять добавить делегат.

У кого-либо есть понимание относительно того, как сделать это?


У меня есть десятки тысяч объектов в словаре, который я должен обновлять каждые тридцать секунд или около этого. Создание новых для обновления свойства, вероятно, не выполнимо. Я должен был бы клонировать существующий объект, обновить его и заменить тот в словаре. Я должен был бы также заблокировать его на время клонироваться/добавлять цикла.Фу.

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

Мое последнее исследование привело меня к быть Параллельным. ForEach, который звучит великолепно, но он, как предполагается, не используется для действий то состояние обновления.

Я также видел упоминание о Взаимно блокируемых. Инкремент, который звучит великолепно, но я все еще должен выяснить, как использовать его на каждом элементе в моем словаре ориентированным на многопотоковое исполнение способом.

12
задан dtb 25 May 2010 в 01:15
поделиться

1 ответ

ConcurrentDictionary не помогает вам с одновременным доступом к элементам сохраненных значений, только с самими элементами.

Если несколько потоков вызывают TestIt, вы должны получить снимок коллекции и заблокировать общие ресурсы (которые являются отдельными значениями словаря):

foreach (KeyValuePair<int, Class1> kvp in dict.ToArray())
{
    Class1 value = kvp.Value;
    lock (value)
    {
        value.Counter = value.Counter + 1;
    }
}

Однако, если вы хотите обновить счетчик для определенного ключа, ConcurrentDictionary может поможет вам атомарно добавить новую пару ключ-значение, если ключ не существует:

Class1 value = dict.GetOrAdd(42, key => new Class1());
lock (value)
{
    value.Counter = value.Counter + 1;
}

AddOrUpdate и TryUpdate действительно предназначены для случаев, когда вы хотите заменить значение для данного ключа в ConcurrentDictionary. Но, как вы сказали, вы не хотите изменять значение, вы хотите изменить свойство значения.

3
ответ дан 2 December 2019 в 20:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: