Какой элемент возвращает ConcurrentDictionary.ElementAt

2

В моем коде я получил ConcurrentDictionary, теперь я хочу перебирать каждый элемент в Словаре, но если условие истинно, я хочу удалить элемент из этого Словаря, чтобы не использовать цикл foreach. Также может случиться, что Словарь получит новый элемент в цикле или удалит его из другого потока. После некоторых исследований я использовал ElementAt.

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

Вот как выглядит мой код, CommandHandler.Timeouter из ConcurrentDictionary:

int current = 0;

while (CommandHandler.Timeouter.Count() > current)
{
    var info = CommandHandler.Timeouter.ElementAt(current);
    var timeoutcooldown = info.Value.LastCommandTime.AddMinutes(1);

    if (timeoutcooldown < DateTime.UtcNow)
       {
           CommandHandler.Timeouter.TryRemove(info.Key, out _);
       }
    else current++;
}
  • 1
    Обратите внимание, что словари не гарантируют определенный последовательный порядок элементов (или пары ключ-значение, в этом отношении). Другими словами, порядок элементов в словарях недетерминирован. Если вы спросите, будет ли элемент с индексом 0 (используемый методом расширения Linq ElementAt ) всегда оставаться с индексом 0, то нет, это не гарантируется ...
  • 0
    Ну, это плохо. Думаю, я мог бы использовать List и использовать Linq для поиска того, что мне нужно.
Показать ещё 11 комментариев
Теги:
multithreading
concurrentdictionary

1 ответ

2

ElementAt просто обрабатывает словарь как IEnumerable<KeyValuePair<TKey, TValue>>. Словари не заказаны. Индекс поэтому бессмысленный. Думайте об элементах, возвращающихся в случайном порядке каждый раз. Кроме того, ElementAt не может сделать этот поток безопасным.

Кажется, вы хотите реализовать срок действия кэша. Рассмотрим просто использование lock для доступа к обычному словарю. Если не так много споров, это будет самое простое и очень быстрое решение.

Альтернативный шаблон кода для этого цикла будет следующим:

var itemsToExpire = myDict.Where(/* compute expiration */).ToList();
foreach (var item in itemsToExpire)
   myDict.Remove(item);

Нет необходимости в каких-либо сложных циклах.

  • 0
    Большое спасибо за ответ, так как elgonzo уже руководил мной, я не буду отмечать это как ответ, но наверняка как голос. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню