ASP.NET – wykonywanie czasochłonnej operacji w wątku

O asynchronicznych kontrolerach pisałem już na blogu, zarówno w czystym ASP.NET jak i ASP.NET MVC.

Czasami jednak chcemy zaimplementować model na wzór “fire&forget”. Oczywiście do tego, dużo bardziej nadają się systemy kolejkowe typu nServiceBus, ale dla bardzo prostych przypadków wystarczy odpalenie wątku i wykonanie jakieś czasochłonnej operacji. Przez czasochłonną mam na myśli taką, która wykonuje się kilka minut, a nie kilka godzin.  Jeśli mamy aż tak skomplikowane operacje, wtedy wykonywanie tego w czystym WebAPI\Web zdecydowanie jest złą praktyką.

Błędnym podejściem wykonania operacji w tle jest:

 public ActionResult ExecuteSomething()
 {
    Task.Factory.StartNew(() =>
    {
	Thread.Sleep(5000);
        // time-consuming operation
    });

    return View("Index");
}

“Zwykły” wątek niestety może być zakończony w każdej chwili przez IIS. W momencie zakończenia akcji, IIS przyjmuje, że pozostałe wątki nie mają znaczenia. W praktyce oznacza to, że restart aplikacji albo jej puli może nastąpić w każdym momencie.

Od .NET Framework 4.5.2 istnieje lepszy sposób, a mianowicie HostingEnvironment.QueueBackgroundWorkItem:

 HostingEnvironment.QueueBackgroundWorkItem((token) =>
 {
      Thread.Sleep(5000);
     // time-consuming operation
 });

Jak widać, kod nie wiele różni się, ale w tym przypadku IIS będzie świadomy zadania. Metoda zawiera również token, który używać należy w celu anulowania zadania (np. gdy aplikacja jest zamykana w IIS, a zadanie jest wciąż wykonywane w tle).

Jak wspomniałem nie jest to przeznaczone dla bardzo długich operacji. Jeśli zależy nam na gwarancji wykonania, wtedy zdecydowanie odradzam używanie tego. Autorzy metody nie dają takiej pewności i jeśli aplikacja webowa będzie musiała zostać zakończona, QueueBackgroundWorkItem może jedynie opóźnić zakończenie AppDomain (o maksymalnie 90 sekund).
HttpContext również domyślnie nie zostanie przekazany.

4 thoughts on “ASP.NET – wykonywanie czasochłonnej operacji w wątku”

  1. @Michal,
    Dzieki, naprawde fajna biblioteka. Szczegolnie dashboard spodobal mi sie. Jedynie co mi brakuje, to wsparcie dla MySQL.

  2. Do operacji wykonywanych cyklicznie, jak generowanie remainderów mailowych, ich wysyłanie, czyszczenie tabel tymczasowych itp. używamy w projekcie Service Brokera. Sprawdza się bardzo dobrze 🙂

Leave a Reply

Your email address will not be published.