Как удалить элемент из вложенного ConcurrentDictionary? - PullRequest
0 голосов
/ 12 февраля 2019

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

private static ConcurrentDictionary<string, ConcurrentDictionary<string, ChatMember>> onlineGroupsMembers = new ConcurrentDictionary<string, ConcurrentDictionary<string, ChatMember>>();

Затем, когда приходит новый участник, я добавляю его:

        onlineGroupsMembers.AddOrUpdate
            (chatKey,
            (k) => // add new
            {
                var dic = new ConcurrentDictionary<string, ChatMember>();
                dic[chatMember.Id] = chatMember;
                return dic;
            },
            (k, value) => // update
            {
                value[chatMember.Id] = chatMember;
                return value;
            });

Теперь проблема в том, как я могу удалить участникаиз внутреннего словаря?также, как удалить словарь из внешнего словаря, когда он пуст?

В параллельном словаре есть TryRemove , но это не помогает, и проверка на ContainsKey , тогда удаление не является атомарным.

Спасибо.

1 Ответ

0 голосов
/ 12 февраля 2019

Чтобы удалить ChatMember из группы, вам нужно получить ConcurrentDictionary<> для этой группы с ...

var groupDictionary = onlineGroupsMembers["groupID"];

... или ...

var groupDictionary = onlineGroupsMembers.TryGetValue("groupID", out ConcurrentDictionary<string, ChatMember> group);

С groupDictionary затем вы попытаетесь удалить участника ...

var wasMemberRemoved = groupDictionary.TryRemove("memberID", out ChatMember removedMember);

Чтобы полностью удалить группу из onlineGroupsMembers, вы должны вызвать TryRemove непосредственно в этом словаре ...

 var wasGroupRemoved = onlineGroupsMembers.TryRemove("groupID", out ConcurrentDictionary<string, ChatMember> removedGroup);

Менее громоздкий способ реализовать это может быть с двумя словарями, которые не являются вложенными.Можно сопоставить идентификатор группы с чем-то вроде ConcurrentBag<> или одновременным HashSet<> (если он существует) из его ChatMember s ...

ConcurrentDictionary<string, ConcurrentBag<ChatMember>> groupIdToMembers;

... или от идентификатора группы к идентификатору ее члена ...

ConcurrentDictionary<string, ConcurrentBag<string>> groupIdToMemberIds;

Обратите внимание, что ConcurrentBag<> допускает дублирование значений.

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

ConcurrentDictionary<string, ChatMember> memberIdToMember;
...