Чтобы исправить ошибку компилятора, вы можете сделать это:
myDic.AddOrUpdate(1, new HashSet<int>() { myFirstElement },
(key, actualValue) => {
actualValue.Add(myFirstElement);
return actualValue;
});
НО это не потокобезопасно, потому что функция «обновить» не запускается внутри какой-либо блокировки, поэтому вы потенциально добавляете к не потокобезопасному HashSet
из нескольких потоков. Это может привести (например) к потере значений (например, вы добавляли 1000 элементов в HashSet
, но в итоге у вас, например, было только 970 элементов). Функция обновления в AddOrUpdate
не должна иметь побочных эффектов, а здесь она есть.
Вы можете заблокировать себя при добавлении значений в HashSet
:
myDic.AddOrUpdate(1, new HashSet<int>() { myFirstElement },
(key, actualValue) => {
lock (actualValue) {
actualValue.Add(myFirstElement);
return actualValue;
}
});
Но тогда возникает вопрос, почему вы в первую очередь используете структуру без блокировки (ConcurrentDictionary
). Кроме того, любой другой код может получить HashSet
из вашего словаря и добавить туда значение без каких-либо блокировок, что сделает все это бесполезным. Поэтому, если вы решили пойти по этому пути по какой-либо причине, вы должны убедиться, что весь код блокируется при доступе к HashSet
из этого словаря.
Вместо всего этого - просто используйте concurrent collection вместо HashSet
. Насколько мне известно, ConcurrentHashSet
нет, но вы можете использовать другой ConcurrentDictionary
с фиктивными ключами в качестве замены (или поискать в Интернете пользовательские реализации).
Примечание. Здесь
myDic.AddOrUpdate(1, new Hashset<int>(){myFirstElement},
вы создаете новый HashSet
каждый раз при вызове AddOrUpdate
, даже если этот словарь не нужен, потому что ключ уже есть. Вместо этого используйте перегрузку с фабрикой добавленной стоимости:
myDic.AddOrUpdate(1, (key) => new HashSet<int>() { myFirstElement },
Изменить: пример использования ConcurrentDictionary
в качестве набора хэшей:
var myDic = new ConcurrentDictionary<long, ConcurrentDictionary<int, byte>>();
long key = 1;
int element = 1;
var hashSet = myDic.AddOrUpdate(key,
_ => new ConcurrentDictionary<int, byte>(new[] {new KeyValuePair<int, byte>(element, 0)}),
(_, oldValue) => {
oldValue.TryAdd(element, 0);
return oldValue;
});
person
Evk
schedule
31.10.2017