Я пытаюсь обновить записи в 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, который звучит великолепно, но он, как предполагается, не используется для действий то состояние обновления.
Я также видел упоминание о Взаимно блокируемых. Инкремент, который звучит великолепно, но я все еще должен выяснить, как использовать его на каждом элементе в моем словаре ориентированным на многопотоковое исполнение способом.
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. Но, как вы сказали, вы не хотите изменять значение, вы хотите изменить свойство значения.