Как реализовать TryRemove условно для ConcurrentDictionary? - PullRequest
2 голосов
/ 24 сентября 2019

Недавно Мне потребовалось для Dictionary, которое я мог бы обновить из нескольких потоков, и очевидным кандидатом на эту работу была встроенная ConcurrentDictionary.К сожалению, в итоге я не использовал его, а вместо этого использовал обычный Dictionary, защищенный lock, из-за фатального ограничения: TryRemove не предлагает перегрузки, которая допускает условное удалениеэлемент.Доступный метод TryRemove удаляет и возвращает удаленный элемент, но в моем случае было необходимо удалить элемент, только если он был вставлен ранее тем же рабочим процессом.Удаление элемента из другого рабочего процесса (даже на долю мкс) может иметь нежелательные последствия, которые я предпочел бы не решать.Поэтому мой вопрос таков: возможно ли изменить существующий класс ConcurrentDictionary с помощью поточно-ориентированного условного метода расширения TryRemove?

Для справки - мой пример использованияСловарь безопасно заполняется с помощью метода AddOrUpdate:

var dict = new ConcurrentDictionary<string, CancellationTokenSource>();
var cts = dict.AddOrUpdate("Key1", key => new CancellationTokenSource(),
    (key, existingValue) =>
{
    existingValue.Cancel();
    return new CancellationTokenSource();
});

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

var removed = dict.TryRemove("Key1", (key, existingValue) =>
{
    return existingValue == cts;
});

Это подпись необходимого метода:

public static bool TryRemove<TKey, TValue>(
    this ConcurrentDictionary<TKey, TValue> source, TKey key,
    Func<TKey, TValue, bool> predicate)
{
    // Is it possible?
}

1 Ответ

0 голосов
/ 24 сентября 2019

Я думаю, что вам нужно реализовать свой собственный Dictionary, который каким-то образом запоминает, какой Task добавил, какой элемент.

Отказ от ответственности

Но я бы порекомендовал удалить все ваши детали, которые привели к этому требованию, поскольку мне кажется несколько странным, что элементы могут быть удалены только при создании рабочего процесса.

Я говорю это потому, что если workflow 1 вставил элемент elm1 и не удалил его, пока он работал.Таким образом, элемент elm1 остается в словаре, и никто не может удалить его, так как завершился процесс создания.

...