Indermove
@Indermove
C#/.NET back-end разработчик

Почему после проверки TryGetValue случается ошибка добавления элемента с таким же ключом?

Добрый день, товарищи, имеется следующий код:

private class ThreadsafeMemoizeCache<TArgument, TResult>
        {
            private Dictionary<TArgument, TResult> cache = new Dictionary<TArgument, TResult>();
            
            public TResult GetOrAdd(TArgument key, Func<TArgument, TResult> valueFactory)
            {
                TResult result;
                
                if (cache.TryGetValue(key, out result))
                {
                    return result;
                }
                lock (this)
                {
                    if (!cache.TryGetValue(key, out result))
                    {
                        result = valueFactory(key);
                        Dictionary<TArgument, TResult> newCache = new Dictionary<TArgument, TResult>(cache);
                        newCache.Add(key, result);
                        cache = newCache;
                    }
                }
                return result;
            }
        }


Вопрос следующего рода. По какой-то причине в данном коде вылезает ошибка добавления уже существующего ключа. При этом такой же ключ добавляется этим же потоком. Попытка модифицировать код вот таким образом тоже ничего не дала:

lock (this)
                {
                    if (cache.TryGetValue(key, out result))
                    {
                        return result;
                    }

                    if (!cache.TryGetValue(key, out result))
                    {
                        result = valueFactory(key);
                        Dictionary<TArgument, TResult> newCache = new Dictionary<TArgument, TResult>(cache);
                        newCache.Add(key, result);
                        cache = newCache;
                    }
                }


В чем может быть причина?
  • Вопрос задан
  • 288 просмотров
Решения вопроса 1
@Hydro
C#/.NET Developer
Во-первых, код я бы переписал так:
private class ThreadsafeMemoizeCache<TArgument, TResult>
    {
      private readonly Dictionary<TArgument, TResult> _internalCache = new Dictionary<TArgument, TResult>();

      private readonly object _internalCacheLocker = new object();

      public TResult GetOrAdd(TArgument key, Func<TArgument, TResult> valueFactory)
      {
        lock (_internalCacheLocker)
        {
          TResult result;
          if (_internalCache.TryGetValue(key, out result))
            return result;

          result = valueFactory(key);
          _internalCache.Add(key, result);
          return result;;
        }
      }
    }


А во-вторых, у меня вот такой код работает:

var cache = new ThreadsafeMemoizeCache<string, string>();
cache.GetOrAdd("1", (arg) => string.Empty);
cache.GetOrAdd("1", (arg) => string.Empty);
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы