MVC3 - использование AsyncController для предварительного заполнения ObjectCache из базы данных
У меня есть форма, которая ищет через AJAX два разных источника данных. Данные относительно невелики, но скорость, с которой они возвращаются, низкая.
Я построил слой кэша для хранения полного результата после первого запроса... однако я хотел бы заполнить кэш данными, прежде чем пользователь выполнит поиск.
Должен ли я смотреть на AsyncController, чтобы сделать это? Любые рекомендации?
Мое желаемое поведение (обновлено):
- Пользователь запрашивает любой ActionABC какого-либо контроллера (не обязательно поисковое действие)
- На стороне сервера это действие проверяет кэш и асинхронно запрашивает данные, если они пусты
- ActionABC возвращает запрошенное представление, пока кэш продолжает заполняться на сервере
- Если пользователь впоследствии выполняет поиск во время заполнения кэша, его запрос ожидает, пока заполнение кэша не будет завершено, иначе данные кэша будут немедленно доступны
2 ответа
Я закончил тем, что не использовал AsyncControllers.
Я использовал фабрику задач, чтобы "запустить и забыть" вызов для начальной загрузки данных при любом вызове контроллера.
Task.Factory.StartNew(() => { var x = GetData(); });
Внутри вызова "GetData" я использовал LOCK, чтобы заставить последующие вызовы ждать, пока кэш не будет заполнен (адреса #4).
private static object ThisLock = new object();
protected MyData GetData()
{
if(<MyData in cache>)
return MyData from cache;
lock(ThisLock)
{
// just entered lock, see if cache was set by previous blocking thread
if(MyData in cache>)
return data from cache;
... load MyData from database ...
... save MyData to cache ...
return MyData from cache;
}
}
Вы можете получить выгоду от асинхронного контроллера, только если бы вы могли выполнять 2 поиска параллельно.
В этом случае ваша логика может быть:
- Если данные найдены в кэше, немедленно верните результат.
- Если данные не найдены в кеше, запустите 2 параллельные асинхронные задачи для выполнения поиска.
- Синхронизируйте эти задачи так, чтобы, как только они оба закончили, вы заполняли кеш и возвращали конечный результат.
Также, если вы идете по маршруту AsyncController, убедитесь, что вы используете async ADO.NET API для запроса вашей базы данных (command.BeginExecuteResult
/command.EndExecuteResult
), чтобы вы могли в полной мере использовать порты завершения ввода-вывода и не блокировать рабочие потоки во время выполнения дорогостоящих операций поиска.