У меня есть приложение ASP.NET с большим количеством динамического содержимого. Содержание одинаково для всех пользователей, принадлежащих конкретному клиенту. Чтобы уменьшить количество обращений к базе данных, необходимых для запроса, я решил кэшировать данные на уровне клиента. Я создал статический класс («ClientCache») для хранения данных.
Наиболее часто используемый метод класса - это, безусловно, «GetClientData», который возвращает объект ClientData, содержащий все сохраненные данные для конкретного клиента. ClientData загружается лениво, хотя: если запрошенные данные клиента уже кэшированы, вызывающая сторона получает кэшированные данные; в противном случае данные извлекаются, добавляются в кэш, а затем возвращаются вызывающей стороне.
В конце концов я начал получать периодические сбои в методе GetClientData в строке, где объект ClientData добавляется в кэш. Вот тело метода:
public static ClientData GetClientData(Guid fk_client)
{
if (_clients == null)
_clients = new Dictionary<Guid, ClientData>();
ClientData client;
if (_clients.ContainsKey(fk_client))
{
client = _clients[fk_client];
}
else
{
client = new ClientData(fk_client);
_clients.Add(fk_client, client);
}
return client;
}
Текст исключения всегда выглядит как «Объект с таким же ключом уже существует».
Конечно, я пытался написать код, чтобы просто не было возможности добавить клиента в кеш, если он уже существует.
На данный момент, я подозреваю, что у меня есть условие гонки, и метод выполняется дважды одновременно, что может объяснить, как происходит сбой кода. Что меня смущает, так это то, как метод может быть выполнен дважды одновременно. Насколько я знаю, любое приложение ASP.NET когда-либо выставляет только один запрос за раз (поэтому мы можем использовать HttpContext.Current).
Итак, является ли эта ошибка вероятной причиной гонки, которая потребует установки блокировок в критических секциях? Или я упускаю более очевидную ошибку?