MVC3 - использование AsyncController для предварительного заполнения ObjectCache из базы данных

У меня есть форма, которая ищет через AJAX два разных источника данных. Данные относительно невелики, но скорость, с которой они возвращаются, низкая.

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

Должен ли я смотреть на AsyncController, чтобы сделать это? Любые рекомендации?

Мое желаемое поведение (обновлено):

  1. Пользователь запрашивает любой ActionABC какого-либо контроллера (не обязательно поисковое действие)
  2. На стороне сервера это действие проверяет кэш и асинхронно запрашивает данные, если они пусты
  3. ActionABC возвращает запрошенное представление, пока кэш продолжает заполняться на сервере
  4. Если пользователь впоследствии выполняет поиск во время заполнения кэша, его запрос ожидает, пока заполнение кэша не будет завершено, иначе данные кэша будут немедленно доступны

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 поиска параллельно.

В этом случае ваша логика может быть:

  1. Если данные найдены в кэше, немедленно верните результат.
  2. Если данные не найдены в кеше, запустите 2 параллельные асинхронные задачи для выполнения поиска.
  3. Синхронизируйте эти задачи так, чтобы, как только они оба закончили, вы заполняли кеш и возвращали конечный результат.

Также, если вы идете по маршруту AsyncController, убедитесь, что вы используете async ADO.NET API для запроса вашей базы данных (command.BeginExecuteResult/command.EndExecuteResult), чтобы вы могли в полной мере использовать порты завершения ввода-вывода и не блокировать рабочие потоки во время выполнения дорогостоящих операций поиска.

Другие вопросы по тегам