Подтвердить что ты не робот

Что такое MemoryCache.AddOrGetExisting для?

Поведение MemoryCache.AddOrGetExisting описывается как:

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

И что он возвращает:

Если существует запись кэша с тем же ключом, существующая запись кэша; иначе, null.

Какова цель метода с этой семантикой? Каков пример этого?

4b9b3361

Ответ 1

Часто возникают ситуации, когда вы хотите создать запись кэша, если соответствующая запись еще не существует (т.е. вы не хотите перезаписывать существующее значение).

AddOrGetExisting позволяет делать это атомарно. Без AddOrGetExisting было бы невозможно выполнить тест get-test в атомарном потокобезопасном режиме. Например:

 Thread 1                         Thread 2
 --------                         --------

 // check whether there an existing entry for "foo"
 // the call returns null because there no match
 Get("foo")

                                  // check whether there an existing entry for "foo"
                                  // the call returns null because there no match
                                  Get("foo")

 // set value for key "foo"
 // assumes, rightly, that there no existing entry
 Set("foo", "first thread rulez")

                                  // set value for key "foo"
                                  // assumes, wrongly, that there no existing entry
                                  // overwrites the value just set by thread 1
                                  Set("foo", "second thread rulez")

(См. также метод Interlocked.CompareExchange, который позволяет использовать более сложный эквивалент на уровне переменной, а также записи wikipedia на test-and-set и compare-and-swap.)

Ответ 2

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

Ответ 3

Ответ LukeH верен. Поскольку другие ответы указывают на то, что семантика метода может интерпретироваться по-разному, я считаю, что стоит отметить, что AddOrGetExisting фактически не будет обновлять существующие записи кэша.

Итак, этот код

Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "one", new CacheItemPolicy()) ?? "(null)");
Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "two", new CacheItemPolicy()));
Console.WriteLine(MemoryCache.Default.AddOrGetExisting("test", "three", new CacheItemPolicy()));

напечатает

(null)
one
one

Еще одна вещь, о которой нужно знать: Когда AddOrGetExisting находит существующую запись кэша, она не будет удалять CachePolicy, переданную вызову. Это может быть проблематично, если вы используете пользовательские мониторы изменений, которые устанавливают дорогостоящие механизмы отслеживания ресурсов. Как правило, при удалении записи кэша система кэширования вызывает Dipose() на ваших ChangeMonitors. Это дает вам возможность отменить регистрацию событий и т.п. Однако, когда AddOrGetExisting возвращает существующую запись, вы должны сами позаботиться об этом.