Огонь и забудь с ASP.NET MVC - PullRequest
23 голосов
/ 16 июня 2011

Я ищу информацию о лучших методах борьбы с пожарами и забыл действие asp.net mvc ... по сути, я хочу, чтобы мобильный клиент позвонил; сервер запускает асинхронную задачу; а затем вернитесь к мобильному клиенту как можно быстрее.

Но я хочу убедиться, что, без исключений, асинхронная задача будет успешно выполнена. Очевидно, есть несколько вариантов:

  • Создать новую тему
  • Поставить в очередь рабочий элемент в ThreadPool
  • Начать асинхронный вызов делегата
  • Запустить задачу

Я предполагаю, что Задача будет лучшим вариантом здесь, но хотел бы получить мысли от SO.

Редактировать: , чтобы уточнить, основываясь на нескольких ответах уже: Клиент не нуждается в ответе. Я хочу, чтобы HTTP-запрос выполнялся как можно быстрее, как только сервер начинает асинхронную задачу. Я знаю об асинхронных шаблонах на клиенте, однако хочу ограничить время, необходимое мобильному устройству для поддержания открытого соединения. Кроме того, вы хотите избежать отдельного процесса, который опрашивает или отправляет сообщение (через очередь, шину и т. Д.), Потому что это излишне. Я просто хочу что-то зарегистрировать в базе данных, клиент не должен оставаться подключенным, пока не завершится IO.

Ответы [ 4 ]

18 голосов
/ 29 июня 2012

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

Вам не нужно AsyncController, потому что вы не заинтересованы в ожидании завершения асинхронных операций. Таким образом, ответ на ваш вопрос в отношении MVC таков: это не имеет значения. Вы можете выполнять свою работу любым способом и выполнять обычное старое действие, которое запускает процесс и возвращает любой желаемый результат.

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

Вы упомянули, что вам не нужен отдельный процесс, и это ограничивает ваши возможности. Ваши задачи будут выполняться в одном домене приложения с вашим веб-приложением. Если что-то разрушит домен приложения или процесс, ваши задачи умрут, возможно, в странном состоянии. Это не обязательно даже из необработанных исключений. IIS может быть настроен на автоматическую перезапуск приложения время от времени или в определенных условиях. Или, если вы выпустите новый код или коснитесь чего-либо в каталоге bin, ваш домен приложения будет разрушен после завершения всех запросов и запуска нового. Если эти дела являются для вас препятствием, то у вас нет другого выбора, кроме как вывести свои задачи из процесса и обмениваться сообщениями с помощью какого-либо сообщения.

Если вы не беспокоитесь о том, что IIS убьет вас, вам все равно придется беспокоиться о себе. Необработанные исключения из других фоновых задач приведут к остановке процесса, если вы не воспользуетесь последним шансом с помощью события AppDomain.UnhandledException. В случае использования библиотеки параллельных задач, задачи с исключениями, которые вы не наблюдаете, Wait или их просмотр или просмотр свойств Result или Exception, приведут к остановке процесса, если у вас не будет последнего шанса. наблюдать их в событии TaskScheduler.UnobservedTaskException.

Еще одно замечание: все потоки ThreadPool, используемые для фоновых операций, не смогут обслуживать запросы для вашего веб-приложения в течение этого времени. Вы можете управлять максимальным количеством потоков в пуле или вместо этого создать новый поток. Или, если вы используете TPL с планировщиком по умолчанию, запланируйте задачу с подсказкой LongRunning, чтобы эффективно получить новый поток.

11 голосов
/ 10 декабря 2012

Очистите огонь и забудьте с TPL и Mvc 4

public async Task<ActionResult> Index() 
{
  // Start all operations.
  var tasks = new[]
  {
    Task.Run(() =>TestOutput.DoWork("1")), 
    Task.Run(() =>TestOutput.DoWork("2")), 
    Task.Run(() =>TestOutput.DoWork("3"))
  };

  // Asynchronously wait for them all to complete.
// Uncomment below line to not forget the results
//  var results = await Task.WhenAll(tasks);

  // Return empty string for fire and forget.
  return View(string.Empty);
} 
1 голос
/ 16 июня 2011

Я бы порекомендовал использовать AsyncController.Вы должны посмотреть на область AsyncController из примера кода для презентации Advanced MVC3 Брэда Уилсона, по адресу http://bradwilson.typepad.com/presentations/advanced-mvc-3.zip

1 голос
/ 16 июня 2011

Вы противоречивы

В заголовке вашего вопроса явно написано "Огонь и забудьте", а затем в своем вопросе вы упоминаете обратное

По сути, я хочу, чтобы мобильный клиент сделалвызов;сервер запускает асинхронную задачу; и затем верните мобильному клиенту как можно быстрее.

Итак, вы хотите асинхронный вызов , который отправит результат обратно, или Запустить и забыть вызов?


Если обычный асинхронный вызов , просто используйте метод jQuery .ajax(), такой же, в вашей любимой библиотеке javascript, и перехватитедо вашего возврата в функции свойства success.


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

...