Как запустить длительный процесс асинхронно под asp.net?

.net 4.5, asp.net mvc: Каков наилучший способ запустить длительный процесс (1-2 минуты) из приложения ASP.NET, если его следует запускать в однопоточной среде, то есть процесс инициируется для только один пользователь за раз, выполнение для всех других пользователей должно ждать, пока не будет выполнено текущее выполнение? Сценарий следующий: пользователь нажимает кнопку, которая запускает какие-то длительные вычисления, HTTP-ответ немедленно возвращается пользователю, затем пользователь должен запросить статус расчетов с отдельным запросом вручную. Отказ http-сессии Asp.net не должен приводить к завершению процесса, он должен продолжаться. Процесс может быть запущен на том же или отдельном сервере.

4 ответа

Решение

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

Я покажу вам, как выполнить эту задачу с http://hangfire.io/ - невероятно простым способом выполнения отложенных и повторяющихся задач в приложениях ASP.NET. Служба Windows не требуется.

Сначала установите пакет через NuGet. Если у вас есть какие-либо проблемы, обратитесь к краткому руководству в официальной документации.

PM> Install-Package Hangfire

Откройте свой класс запуска OWIN и добавьте следующие строки:

public void Configure(IAppBuilder app)
{
    GlobalConfiguration.Configuration.UseSqlServerStorage("connection_string");

    app.UseHangfireDashboard();
    app.UseHangfireServer();
}

Затем напишите метод, который будет выполнять длительную работу (я применил атрибут для выполнения только одного метода за раз):

[DisableConcurrentExecution]
public void LongRunning()
{
    // Some processing stuff
}

А затем вызовите метод в фоновом режиме как fire-and-забудьте, чтобы немедленно ответить пользователю:

public ActionResult Perform()
{
    BackgroundJob.Enqueue(() => LongRunning());
    return View();
}

Если вы хотите уведомить пользователя о завершении работы, рассмотрите возможность использования SignalR и добавьте LongRunning метод соответственно.

.Net 4.5.2 добавляет QueueBackgroundWorkItem, который можно использовать для планирования задачи. Если вы не управляете сервером (когда он перезагружен), 90-секундная задержка закрытия appPool по умолчанию не будет работать (если вы не можете обнаружить, что задача не была выполнена и запущена на другом сервере). Дополнительные сведения см. В разделе " QueueBackgroundWorkItem для надежного планирования и запуска фоновых процессов в ASP.NET".

Если вы управляете сервером и нуждаетесь в большей простоте, чем полноценный фреймворк, такой как Hangfire, вы можете создать консольное приложение (.exe) и сделать любую вещь..., затем вы можете вызвать.exe с помощью метода Process.Start, вы можно вызвать.exe с SQL Server на сервис, и т.д.

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