Fire and Forget с ASP.NET MVC
Я ищу информацию о лучших методах пожара и забыл действие asp.net mvc... по существу, я хочу, чтобы мобильный клиент сделал вызов; сервер запускает асинхронную задачу; а затем вернитесь к мобильному клиенту как можно быстрее.
Но я хочу убедиться, что, не допуская никаких исключений, задача async завершится успешно. Очевидно, есть несколько разных вариантов:
- Создать новую тему
- Очередь рабочего элемента в ThreadPool
- Начать вызов делегата async
- Запустить задачу
Я предполагаю, что задача будет лучшим вариантом здесь, но хотела получить мысли от SO.
Изменить: уточнить на основе нескольких ответов уже: клиенту не нужен ответ. Я хочу, чтобы HTTP-запрос был выполнен как можно быстрее, как только сервер запустил задачу async. Я знаю об асинхронных шаблонах на клиенте, однако я хочу ограничить время, необходимое мобильному устройству для поддержания открытого соединения. Кроме того, вы хотите избежать отдельного процесса, который опроса или нажал сообщение (через очередь, шину и т.д.), Потому что это перебор. Я просто хочу зарегистрировать что-то в базе данных, клиент не должен оставаться подключенным до тех пор, пока этот IO не будет завершен.
Ответы
Ответ 1
Я знаю, что это старый вопрос, но здесь я беру на себя такие вещи, за что это стоит, поскольку я не согласен с принятым ответом.
Вам не нужно AsyncController
, потому что вам не нужно ждать завершения операций async. Поэтому ответ на ваш вопрос в отношении стороны MVC заключается в следующем: это не имеет значения. Вы можете выполнять свою работу любым способом и иметь только обычное старое действие, которое запускает процесс и возвращает любой результат, который вы хотите.
Вторая часть вашего вопроса действительно более актуальна. Вы хотите убедиться, что ничего не случится с вашими асинхронными задачами, учитывая, что вы запустили их из своего веб-процесса, считая, что сама задача не выдает исключения. Ответ на это зависит от ваших требований к надежности.
Вы упомянули, что вам не нужен отдельный процесс, и это ограничивает ваши варианты. Ваши задачи будут выполняться в одном домене приложения с вашим веб-приложением. Если что-то сбивает домен приложения или процесс, ваши задачи умрут, возможно, в странном состоянии. Это не обязательно даже из необработанных исключений. IIS может быть настроен на автоматическую переработку приложения время от времени или в определенных условиях. Или, если вы выпустите новый код или коснитесь чего-либо в каталоге bin, ваш домен приложения будет разорван после завершения всех запросов и будет запущен новый. Если эти случаи для вас - шоу-стоппер, тогда у вас нет выбора, кроме как перевести свои задачи из процесса и общаться с каким-то сообщением.
Если вы не беспокоитесь о том, что IIS убил вас, вам все равно придется беспокоиться о себе. Необработанные исключения из других фоновых задач приведут к разрушению процесса, если вы не воспользуетесь последним событием с событием AppDomain.UnhandledException
. В случае использования параллельной библиотеки задач Задачи с исключениями, которые вы не наблюдаете при использовании Wait
ing на них или просмотра свойств Result
или Exception
, приведут к разрушению процесса, если вы не используете последний шанс наблюдайте их в событии TaskScheduler.UnobservedTaskException
.
Еще одно замечание: любые потоки ThreadPool, используемые для фоновых операций, не смогут выполнять запросы для вашего веб-приложения в течение этого времени. Вы можете управлять максимальными потоками в пуле или вместо этого запускать новый поток. Или, если вы используете TPL с планировщиком по умолчанию, запланируйте задачу с помощью подсказки LongRunning
, чтобы эффективно получить новый поток.
Ответ 2
Очистить огонь и забыть 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);
}
Ответ 3
Вы противоречивы
В заголовке вашего вопроса явно указано "Огонь и Забыть", а затем в вашем вопросе вы указываете обратное
В основном я хочу, чтобы мобильный клиент сделал вызов; сервер запускает асинхронную задачу; , а затем верните мобильному клиенту как можно быстрее.
Итак, вам нужен асинхронный вызов, который отправит результат назад или вызов Огонь и забыть?
Если обычный асинхронный вызов, просто используйте метод jQuery .ajax()
, который вы одинаково используете в своей любимой библиотеке javascript, и подключите свое возвращение в функции свойств success
.
Если огонь и забудьте, лучше всего попросить сервер вставить строку в таблицу TBL_JOBS
в базе данных, тогда вы можете иметь повторяющийся script, который выбирает этот и обрабатывать информацию.
Ответ 4
Я бы рекомендовал использовать AsyncController
. Вы должны посмотреть область AsyncController из примера кода для презентации Brad Wilson Advanced MVC3, http://bradwilson.typepad.com/presentations/advanced-mvc-3.zip