В моем коде я получил 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++;
}
ElementAt
просто обрабатывает словарь как IEnumerable<KeyValuePair<TKey, TValue>>
. Словари не заказаны. Индекс поэтому бессмысленный. Думайте об элементах, возвращающихся в случайном порядке каждый раз. Кроме того, ElementAt
не может сделать этот поток безопасным.
Кажется, вы хотите реализовать срок действия кэша. Рассмотрим просто использование lock
для доступа к обычному словарю. Если не так много споров, это будет самое простое и очень быстрое решение.
Альтернативный шаблон кода для этого цикла будет следующим:
var itemsToExpire = myDict.Where(/* compute expiration */).ToList();
foreach (var item in itemsToExpire)
myDict.Remove(item);
Нет необходимости в каких-либо сложных циклах.
ElementAt
) всегда оставаться с индексом 0, то нет, это не гарантируется ...