Ritorna alla vista con attesa asincrona

Ho un processo che vorrei eseguire in background. Questo viene eseguito con un clic di un link di azione.

Azione da chiamare:

public async Task ProcessRec() { await Task.Run(() => waitTimer()); return RedirectToAction("Index", "Home"); } public void waitTimer() { Thread.Sleep(10000); } 

Ciò tuttavia attende per tutti i 10 secondi prima di reindirizzarmi alla mia azione “Index, Home”. Sono molto nuovo in Await / Async quindi so che sto interpretando qualcosa di sbagliato qui. Come faccio a ottenere l’applicazione per tornare a questa azione, mentre il waitTimer è in esecuzione in background? Grazie!!

await , come hai scoperto, blocca la risposta dal tornare all’utente prima che sia terminata. Normalmente dovresti mettere il lavoro in background su un altro thread e impostarlo su “fire and forget” non aspettandolo, tuttavia in ASP.NET IIS chiuderà AppDomains che non viene utilizzato e Task.Run non informa IIS che il tuo background thread “utilizza l’AppDomain” in modo che il thread in background possa essere terminato con un Thread.Abort() durante un arresto di AppDomain.

Se si utilizza .NET 4.5.2 o versione successiva, è ansible indicare a IIS che si dispone di un worker in background che è necessario mantenere QueueBackgroundWorkItem tramite QueueBackgroundWorkItem . Lo useresti in questo modo

  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); } 

Ora questo non garantisce che IIS non spenga il dominio della tua app ma fa sapere che sei nel mezzo di qualcosa e ti chiede più tempo quando prova a spegnerlo (ottieni fino a 90 secondi aggiuntivi dopo un l’arresto viene avviato per completare tutti gli elementi di sfondo in coda per impostazione predefinita).

Per maggiori informazioni leggi questo blog MSDN presentandolo.

Ciò tuttavia attende per tutti i 10 secondi prima di reindirizzarmi alla mia azione “Index, Home”.

Giusto, è perché await modo asincrono il completamento delle operazioni. Restituirà il thread alla piscina fino al completamento dell’operazione.

Come faccio a ottenere l’applicazione per tornare a questa azione, mentre il waitTimer è in esecuzione in background?

Task.Run è pericoloso nel fatto che non registra il lavoro con IIS che può causare problemi . Invece, puoi usare BackgroundTaskManager o HangFire che registrano la sua esecuzione con ASP.NET:

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

Sto pensando di inviare un messaggio a una coda (come la memoria di azure / coda di servizio) in modo da poter ottenere immediatamente la tua risposta.

E quindi creare un altro servizio per rimandare e elaborare il messaggio (eseguire l’attività a esecuzione prolungata)

Inoltre, se si tratta di un sito Web azure (app Web), è ansible utilizzare il lavoro Web!

Spero che sia d’aiuto.