Hintergrundaufgaben unter ASP.NET ausführen 👍 👎

Im Vergleich zu manch anderen Laufzeitumgebungen für Web-Anwendungen ist es bei ASP.NET auch hier recht einfach, Aufgaben im Hintergrund (beispielsweise über separate Threads) auszuführen. Obwohl das grundsätzlich jederzeit sehr einfach – abgesehen von den inhärenten Schwierigkeiten, die Nebenläufigkeit mit sich bringen kann – möglich ist, ist das einfache Vorgehen, wie man es aus dem Desktop-Bereich kennt, fehleranfällig.

Im einfachsten Fall würde man asynchron per Task.Run(…) (als mit häufig genutzten Standardwerten vorbelegte Abkürzung für Task.Factory.StartNew(…)) zur Verwendung des Standard-Thread-Pools oder manuell per Thread-Klasse arbeiten. Dies ist jedoch insofern problematisch, als dass die ASP.NET-Anwendungsdomäne davon nicht benachrichtigt wird und daher beispielsweise einerseits auf die Beendigung des Vorgangs nicht gewartet und andererseits auf das Herunterfahren des Arbeitsprozesses nicht reagiert werden kann.

Bereits seit längerer Zeit werden daher u. a. die beiden Methoden RegisterObject und UnregisterObject der HostingEnvironment-Klasse zur Verfügung gestellt, deren Verwendung jedoch etwas umständlich ist und auf Grund neuerer Möglichkeiten, die gleich im Anschluss vorgestellt werden, an dieser Stelle nicht weiter ausgeführt werden soll. Wir verwenden stattdessen die seit .NET 4.5.2 verfügbare QueueBackgroundWorkItem-Methode:
Hintergrundaufgabe hinzufügen
010203
HostingEnvironment.QueueBackgroundWorkItem(cT => {    /* Implementierung der Aufgabe */});
Etwas ungeschickt ist es jedoch, wenn dies beispielsweise in einem separaten Projekt ausgelagert werden soll, um jeweils von einer Desktop- und Web-Anwendung darauf zuzugreifen – außerhalb der ASP.NET-Laufzeitumgebung ist die Verwendung dieser Methode nämlich nicht möglich. Daher stellen wir für diesen Fall eine Alternative zur Verfügung, um zumindest ähnliches Verhalten für alle Anwendungsfälle zur Verfügung zu stellen:
Hilfsmethode (inkl. Fallback) implementieren
010203040506070809101112
public static class TaskUtility {    public static void DoBackgroundWork(        Action<CancellationToken> action,        CancellationToken cancellationToken = default(CancellationToken)    ) {        if(HostingEnvironment.IsHosted) {            HostingEnvironment.QueueBackgroundWorkItem(action);        } else {            Task.Run(() => action(cancellationToken), cancellationToken);        }    }}
Hilfsmethode verwenden
010203
TaskUtility.DoBackgroundWork(cT => {    /* Implementierung der Aufgabe */});
Alternativ wäre es natürlich auch möglich, nur die eigentliche Aufgabe auszulagern und dann anwendungsspezifisch zu starten. Weiterführende Informationen zur Verwendung des CancellationToken stellt das MSDN insbesondere über die Struktur CancellationToken und die Klasse CancellationTokenSource zur Verfügung.


Projektverweise

Kategorien / Archiv  |  Übersicht RSS-Feed

Schlagworte

Suche