5

У меня есть процесс, который я хотел бы запустить в фоновом режиме. Это выполняется щелчком ссылки действия.Вернуться к просмотру с Async Await

действий по телефону:

public async Task<ActionResult> ProcessRec() 
    { 
     await Task.Run(() => waitTimer()); 
     return RedirectToAction("Index", "Home"); 
    } 

    public void waitTimer() 
    { 
     Thread.Sleep(10000); 
    } 

Это, однако, ожидает в течение полных 10 секунд перед перенаправлением меня к "Index, Home" действия. Я очень новичок в Await/Async, поэтому я знаю, что интерпретирую здесь что-то не так. Как заставить приложение вернуться к этому действию, а waitTimer выполняется в фоновом режиме? Благодаря!!

+0

Какая версия .NET вы используете. В .NET 4.5.2 появилась функция, позволяющая сделать это «правильно» проще. –

+1

Я использую .NET 4.5 –

+0

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

ответ

4

await, как вы выяснили, блокирует ответ от возврата пользователю до его завершения. Обычно вы просто помещаете фоновый рисунок в другой поток и устанавливаете его «стрелять и забывать», не ожидая, однако в ASP.NET IIS отключит AppDomains, которые не используются, и Task.Run не сообщает IIS, что ваш фоновый поток " использует AppDomain ", поэтому ваш фоновый поток может быть завершен с помощью Thread.Abort() во время отключения AppDomain.

Если вы используете .NET 4.5.2 или новее, вы можете сообщить IIS, что у вас есть работник фона, который вам нужно сохранить в сети через QueueBackgroundWorkItem. Вы бы использовать его как этот

public ActionResult ProcessRec() 
    { 
     HostingEnvironment.QueueBackgroundWorkItem(waitTimer); 
     return RedirectToAction("Index", "Home"); 
    } 

    public void waitTimer(CancellationToken token) 
    { 
     Thread.Sleep(10000); 
    } 
    //You also could do 
    public async Task waitTimer2(CancellationToken token) 
    { 
     await Task.Delay(10000); 
    } 

Теперь это не гарантирует, что IIS не закроет свой домен приложения, но это позволит ему знать, вы находитесь в середине что-то и просит больше времени, когда он действительно пытается выключите его (вы получите до 90 дополнительных секунд после того, как по умолчанию будет завершено завершение всех поставленных по очереди элементов фона).

Для получения дополнительной информации прочитайте this MSDN blog, представляя его.

+0

No HostingEnvironment.QueueBackgroundWorkItem в 4.5 – rnofenko

+1

Он сказал, что .NET 4.5.2. –

+0

Я обновил до 4.5.2, и выше все отлично работает для моих нужд! Очень признателен! –

1

Я подумываю о отправке сообщения в очередь (например, в очереди azure storage/service bus queue), чтобы вы могли немедленно получить ответ.

А затем создать другую службу и обработать из очереди сообщений (выполнить свою длинную выполняемую задачу)

Кроме того, если это лазурь веб-сайт (веб-приложение), вы можете использовать веб-работу!

Надеюсь, что это поможет.

2

Это, однако, ждет все 10 секунд, прежде чем перенаправить меня на мое действие «Индекс, дом».

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

Как я могу заставить приложение вернуться к этому действию, а waitTimer выполняется в фоновом режиме?

Task.Run опасен в том, что он не регистрирует работу с IIS which can lead to problems. Вместо этого, вы можете использовать BackgroundTaskManager или HangFire которые регистрируют это исполнение с ASP.NET:

BackgroundTaskManager.Run(() => { waitTimer() }; 
return RedirectToAction("Index", "Home"); 
+0

Две связанные библиотеки - очень хорошие альтернативы, если вы не можете обновить до 4.5.2, чтобы использовать 'QueueBackgroundWorkItem'. –

+0

@Scott Да, я видел, что он сказал .NET 4.5 :) –