Использование 'HttpContext. Текущий. Кэш' безопасно

Я использую Cache в методе веб-сервиса как это:

var pblDataList = (List<blabla>)HttpContext.Current.Cache.Get("pblDataList");

if (pblDataList == null)
{
    var PBLData = dc.ExecuteQuery<blabla>(@"SELECT blabla");

    pblDataList = PBLData.ToList();

    HttpContext.Current.Cache.Add("pblDataList", pblDataList, null,
        DateTime.Now.Add(new TimeSpan(0, 0, 15)),
        Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
}

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

Запрос занимает 5 - 8 секунд. Был бы, представляя оператор блокировки вокруг этого кода, предотвращают какие-либо возможные конфликты? (Я знаю, что несколько запросов могут работать одновременно, но я хочу быть уверенным, что только один запрос работает за один раз.)

14
задан DavidRR 23 August 2017 в 15:58
поделиться

3 ответа

Объект кэша является потокобезопасным , но HttpContext.Current не будет доступен из фоновых потоков. Это может относиться или не относиться к вам здесь, из вашего фрагмента кода не очевидно, используете ли вы на самом деле фоновые потоки, но в случае, если вы используете сейчас или решите использовать это в какой-то момент в будущем, вам следует сохранить это в уме.

Если есть вероятность, что вам понадобится доступ к кешу из фонового потока, используйте вместо него HttpRuntime.Cache .

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

Однако в большинстве случаев вам действительно нужно сначала профилировать и посмотреть, действительно ли это проблема. Большинство веб-приложений / сервисов не заботятся об этом аспекте кеширования, потому что они не имеют состояния, и не имеет значения, будет ли кеш перезаписан.

22
ответ дан 1 December 2019 в 11:59
поделиться

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

Другой вопрос, однако, - это потокобезопасность данных . Нет никакой гарантии, что каждый List изолирован - это зависит от кеш-провайдера. Поставщик кэша в памяти хранит объекты напрямую, поэтому существует риск коллизий, если какой-либо из потоков редактирует данные (добавляет / удаляет / меняет местами элементы в списке или изменяет свойства одного из элементов). Однако с поставщиком сериализации все будет в порядке. Конечно, это требует, чтобы blabla была сериализуемой ...

1
ответ дан 1 December 2019 в 11:59
поделиться

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

(Обычно это не составляет большой проблемы, но в случае длительного запроса это может быть полезно для уменьшения нагрузки на базу данных.)

2
ответ дан 1 December 2019 в 11:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: