Обработка асинхронного запроса в ASP.NET MVC - PullRequest
6 голосов
/ 28 марта 2012

У меня есть приложение ASP.NET MVC3, которое обрабатывает трудоемкие процессы (копирование большого файла из сети).Что мы хотим сделать:

  1. Пользователь нажимает кнопку, чтобы опубликовать форму, чтобы запустить процесс
  2. Приложение запускает новый поток, чтобы начать копирование файла
  3. Приложение показывает сообщение о том, что процесс копирования файла начался
  4. Пользователь может закрыть браузер, пока копирование обрабатывается и завершается в фоновом режиме.

Идея состоит в том, что пользователь не 'не требуется никакого подтверждения о ходе процесса или уведомление об окончании процесса.

В настоящее время мы позволяем контроллеру инициировать событие в службе Windows и используем службу Windows для выполнения фактической работы.Мне интересно, есть ли лучший / более чистый способ сделать это?

Ответы [ 3 ]

6 голосов
/ 28 марта 2012

Вы можете использовать System.Threading.Tasks.Task , вызывая метод StartNew с делегатом действия .

.контроллер будет выглядеть примерно так:

[HttpPost]
public ActionResult DoSomethingLongRunning()
{
   if (ModelState.IsValid)
   {
       Task.Factory.StartNew(() => 
                   fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2));

       return RedirectToAction("View Indicating Long Running Progress");
   }
   else
   {
        // there is something wrong with the Post, handle it
        return View("Post fallback view");
   }
}

Другой вариант - вы можете использовать System.Reactive.Concurrency и интерфейс IScheduler с TaskPoolScheduler как конкретная реализация для выполнения действия (возможно, внедренная в конструктор контроллера.

public ActionResult DoSomethingLongRunning()
{
   if (ModelState.IsValid)
   {
       ISchedulerImplementation.Schedule(new Action(() =>
        {
            fileCopier.CopyFile(CopyFileParameter1, CopyFileParameter2);
        }));
        return RedirectToAction("View Indicating Long Running Progress");
   }
   else
   {
        // there is something wrong with the Post, handle it
        return View("Post fallback view");
   }
}

В качестве преимущества, если вы сделаете это таким образом, вы можете использовать TestScheduler в качестве реализацииинтерфейс, когда вы проводите модульное тестирование.

3 голосов
/ 28 марта 2012

Я думаю, что размещение хоста Windows Service - ваш лучший вариант.Если он размещен в IIS, вы всегда рискуете, что пул приложений, в котором он запущен, может быть уничтожен за неактивность.

Одна из связанных с этим возможностей заключается в размещении службы WCF внутри службы Windows и предоставлении внешнего HTTP или другой конечной точкиоказание услуг.Таким образом, ваш веб-интерфейс может вызывать «контрактный» метод начала вашей службы WCF и, возможно, другие методы, если это необходимо.

2 голосов
/ 29 марта 2012

Я отправлю запрос в службу WCF MSMQ, размещенную в IIS 7 WAS. Есть потрясающая статья , как ее настроить.

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

Это может быть проблематично, даже катастрофически, если длительный процесс прерывается из-за кратковременной потери сетевого подключения или перезагрузки удаленного сервера. Если ваш длительный процесс включает в себя дополнительную обработку, например, разархивирование файла или его анализ, вы можете подвергнуться дальнейшему риску сбоя, если недостаточно памяти для выполнения обработки. Пользователи могут отправлять слишком много запросов, и не хватает ресурсов для решения одновременных проблем. Если вы позволите приложению ASP.NET MVC выполнять обработку через асинхронные контроллеры , то вы можете быть удивлены, когда ваш длительный процесс прерывается, когда IIS перезапускает рабочий процесс.

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

Размещение его в IIS, а не в службе Windows, предоставляет дополнительные возможности. Например, рабочий процесс IIS можно перезапустить, если он заблокирован или превысит порог памяти. Последнее может быть проблемой, когда вы используете некоторый нативный код для выполнения обработки. Вы можете перерабатывать его каждые четыре (выбирайте сроки) часа. Последнее довольно важно при работе с большими двоичными объектами управляемой памяти, потому что со временем головка большого объекта фрагментируется настолько, что становится почти невозможно управлять выделением достаточного количества памяти для другого большого запроса. Вы можете обнаружить, что служба WCF, размещенная в службе Windows, может страдать от этой проблемы.

В действительности это зависит от того, насколько надежным вы хотите, чтобы этот фоновый процесс был. Если нет, то использование WCF, MSMQ и IIS может быть просто излишним.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...