2015-05-24 21 views
5

Mam proces chciałbym uruchomić w tle. Jest to wykonywane za pomocą kliknięcia linku akcji.Powrót do widoku z Async Oczekiwanie na

Action zadzwonić:

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

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

To jednak czeka na pełne 10 sekund przed przekierowanie mnie do "Indeksu, Home" działania. Jestem bardzo nowy w Await/Async, więc wiem, że interpretuję tutaj coś niewłaściwego. Jak mogę zwrócić aplikację do tej akcji, gdy waitTimer działa w tle? Dzięki!!

+0

Która wersja .NET używasz. .NET 4.5.2 wprowadził funkcję, która ułatwia "robienie tego". –

+1

Używam .NET 4.5 –

+0

Zmieniłem twój tytuł. Zobacz, "[Czy w tytułach pytania powinny znaleźć się" znaczniki "?] (Http://meta.stackexchange.com/questions/19190/)", gdzie konsensus brzmi "nie, nie powinien". –

Odpowiedz

4

await, jak dowiedziałeś się, blokuje odpowiedź od powrotu do użytkownika, zanim zostanie to zrobione. Zwykle po prostu wstawilibyśmy swoje prace w tle do innego wątku i ustawialiśmy go tak, by "strzelał i zapominał", nie czekając, jednak w ASP.NET IIS wyłączy AppDomains, które nie są używane, a Task.Run nie informuje IIS, że twój wątek tła " używa AppDomain ", więc wątek w tle mógł zostać zakończony z Thread.Abort() podczas zamykania AppDomain.

Jeśli korzystasz z .NET 4.5.2 lub nowszego, możesz poinformować IIS, że masz pracownika pracującego w tle, którego musisz utrzymywać przy życiu przez QueueBackgroundWorkItem. Można by użyć go jak ten

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

Teraz to nie gwarantuje, że usługi IIS nie będzie wyłączyć aplikację domenę, ale nie pozwól, że wiesz, że jesteś w środku coś i prosi o więcej czasu, gdy nie próbuje wyłącz go (otrzymujesz do 90 dodatkowych sekund po zakończeniu zamykania, aby domyślnie ukończyć wszystkie oczekujące elementy tła). Aby uzyskać więcej informacji, przeczytaj

.

+0

Brak HostingEnvironment.QueueBackgroundWorkItem w wersji 4.5 – rnofenko

+1

Powiedział .NET 4.5.2. –

+0

Zaktualizowałem do wersji 4.5.2, a powyższe działa idealnie na moje potrzeby! Bardzo doceniane! –

1

Zastanawiam się nad wysłaniem wiadomości do kolejki (jak kolejka błękitnego magazynu/kolejki usług), aby natychmiast uzyskać odpowiedź.

a następnie utworzyć kolejną usługę dequeue i przetwarzać wiadomość (wykonać swoje zadanie długiej jazdy)

Także jeśli jest to Azure www (aplikacja internetowa), można użyć zadania internetowej!

Nadzieję, że pomaga.

2

To jednak czeka na pełne 10 sekund przed przekierowaniem mnie do mojej akcji "Index, Home".

Dobrze, to dlatego, że await asynchronicznie czeka na zakończenie operacji. Spowoduje to przywrócenie wątku do puli, dopóki operacja nie zostanie zakończona.

W jaki sposób mogę przywrócić aplikację do tej akcji, gdy narzędzie waitTimer działa w tle?

Task.Run jest niebezpieczny w tym, że nie rejestruje pracy z IIS which can lead to problems. Zamiast tego można użyć BackgroundTaskManager lub HangFire który zarejestrować to wykonanie z ASP.NET:

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

Dwie połączone biblioteki to bardzo dobre alternatywy, jeśli nie można dokonać aktualizacji do wersji 4.5.2, aby użyć 'QueueBackgroundWorkItem'. –

+0

@Scott Yeah, widziałem, że powiedział .NET 4.5 :) –

Powiązane problemy