Work-Items machen die eigentliche Arbeit. Work-Items sind Instanzen der serialisierbaren Worker-Klassen und Zeilen in Tabelle OrmWorkItem. Die Worker Klassen sind immer individuell für den Anwendungfall.

  • Jede Art einer Aufgabe hat eine implementierende Klasse.
  • Jede zu erledigende Aufgabe hat genau eine InstanceGuid. Die Aufgabe wird in der API immer über diese identifiziert.
  • Zu einer Aufgabenart kann es beliebig viele Aufgaben geben.
  • Jede Instanz eines Work-Items hat eine Oid. Diese ist nur intern.
  • Eine Aufgabe kann in mehreren Teilschritten (Instanzen) erledigt werden, z.B. wegen Unterbrechung durch Anwendungsneustart.
  • Instanzen entstehen, wenn sie eingeplant werden, und sind am Ende ihrer Lebensdauer, wenn sie Abgeschlossen oder aus irgendeinem Grund abgebrochen sind.
  • Die Priorität eines Work-Items richtet sich nach ExpectedRunTime sowie der geplanten Startzeit.

Zustände von Work-Items

  • Bei allen Zuständen, bei denen das WorkItem noch nicht (=nie) ausgeführt wurde, gehört die Instanz dem Work-Manager. Nur er darf Veränderungen vornehmen.
  • Bei allen Zuständen ab dem Start der Ausführung gehört die Instanz dem WorkItem selbst. Nur dieses darf noch Veränderungen vornehmen.
  • Der Zustand von Instanzen von Work-Items ist immer ein gerichteter Graph. Wenn an einem noch nicht aktiven Work-Item eine Veränderung vorgenommen wird, wird eine neue Instanz erstellt und die alte gelöscht.
    Einzige Ausnahme: man kann die Starzeit eines geplanten Workers nachträglich ändern.
  • Die Zustände gehören zu Kategorien, die sich bezüglich vieler Eigenschaften gleich verhalten. 
Kategorie Zustand Beschreibung
Warten auf Startbedingung WaitingForStart Das Work-Item liegt in der Datenbank und wartet bis der Zeitpunkt für seine Ausführung gekommen ist.
Warten auf Startbedingung WaitingForPredecessor Das Work-Item ist bereit zur Ausführung, muss aber noch auf die Beendigung eines Vorgängers warten.
Dies passiert z.B. wenn ein Prozess einen Nachfolger schon eingeplant hat, selbst aber noch in WorkItemFinished hängt.
Warten auf Startbedingung Suspended Das Work-Item hat aktuell keinen geplanten Ausführungszeitpunkt, es ist aber inklusive seine Zustands noch gespeichert.
Es kann nur per ChangeStartTime wieder erweckt werden, ohne seinen Zustand zu verlieren.
Warten auf Ausführung Queued Das Work-Item ist bereit zur Ausführung, steht aber noch in der Warteschlange für eine freie Prozess-Ressource.
Warten auf Ausführung Removing Das Work-Item wurde von Benutzer (bzw. über die API) abgebrochen, bevor es gestartet wurde.
Die Abbruchfunktion wird ebenfalls asynchron über die Warteschlange ausgeführt.
Laufend Running Das Work-Item wird gerade ausgeführt.
Laufend ShutdownRequest Die Anwendung wird gerade heruntergefahren und das Work-Item sollte sich in Kürze beenden und einen Nachfolger einplanen.
Laufend CancellingBySystem Das Work-Item hat seine max. Ausführungszeit erreicht und wird in Kürze gekillt.
Spätestens jetzt sollte es seine Arbeit geordnet beenden und ggf. einen nächsten Start einplanen.
Laufend CancellingByUser Das Work-Item hat den Befehl zum Abbrechen bekommen und sollte sich in Kürze beenden.
Beendet Finished Das Work-Item hat seine Arbeit erfolgreich abgeschlossen.
Beendet Removed Das Work-Item wurde vor dem normalen Start abgebrochen und hatte Gelegenheit, um darauf zu reagieren.
Beendet ShutdownConfirmed Das Work-Item hat sich aufgrun eines Anwendungsneustarts vorzeitig beendet.
Dieser Status ist normalerweise transient und wird sofort zu ShutdownRestart weiter geschaltet.
Beendet Aborted Das Work-Item wurde aufgrund einen Anwendungsneustarts hart abgebrochen und wird neu eingeplant.
Dieser Fall tritt nur ein, wenn ein Work-Item nicht binnen angemessener Zeit auf ShutdownRequest reagiert hat oder der Anwendungspool abgestüzt ist.
Dieser Status ist transient und wird sofort zu AbortedRestart weiter geschaltet.
Beendet Timeout Das Work-Item hat auf den CancellingBySystem Status reagiert und sich selbst beendet.
Standardmäßig wird das Work-Item (wenige male) mit leichtem Zeitversatz neu eingeplant. In diesem Fall ist der Status transient und wird sofort in TimeoutRetry weiter geschaltet.
Wenn die Anzahl der automatischen Restarts überschritten ist, wird dieser Status persistent.
Beendet Killed Das Work-Item hat seine Arbeit nicht binnen der gesetzten Zeit beendet und wurde vom Work-Manager gekillt – gefährlich!
Beendet Cancelled Das Work-Item wurde vom Benutzer (bzw. über die API) abgebrochen und hat sich selbst beendet.
Beendet Error Eine unbehandelte Ausnahme ist aufgetreten.
Bei einer unbehandelten Ausnahme wird das Work-Item (wenige male) mit leichtem Zeitversatz neu eingeplant. In diesem Fall ist der Status transient und wird sofort in ErrorRetry weiter geschaltet.
Wenn die Anzahl der automatischen Restarts überschritten ist, wird dieser Status persistent.
Neustart Reschedule Das Work-Item hat sich erfolgreich beendet und einen Nachfolger eingeplant.
Das kann sowohl aufgrund eines Wiederkehrenden Work-Items der Fall sein als auch wegen eines Timeouts oder sonstiger Limitierungen.
Neustart ShutdownRestart Das Work-Item hat sich aufgrun eines Anwendungsneustarts vorzeitig beendet und erneut eingeplant.
Neustart AbortedRestart Das Work-Item wurde aufgrund einen Anwendungsneustarts hart abgebrochen und sich (nach dem Neustart) neu eingeplant.
Neustart TimeoutRetry Das Work-Item wurde nach einem Timeout neu eingeplant.
Neustart ErrorRetry Das Work-Item wurde nach einer Exception neu eingeplant und wird seine Arbeit bald in einer neuen Instanz fortsetzen.

Statusübergänge

Legende:

  • Graue Linien bedeuten neue Work-Item Instanzen. Dabei geht deren Zustand verloren.
  • Linien, die an farbigen Kästen starten, beginnen an jedem Beliebigem Zustand des Kastens.

Lebenszyklus von Work-Items

  • Eine Instanz entsteht nur, wenn sie über die Work-Manager-API eingeplant wird.
  • Eine noch nicht gestartete Instanz kann über eine erneute Einplanung mit derselben InstanceGuid beliebig ersetzt werden.
  • Für jede einmal erfolgreich eingeplante Instanz (gleiche InstanceGuid), die nicht durch eine erneute Einplanung aktualisiert wurde, wird genau einmal die Methode WorkItemFinished aufgerufen, auch bei einem Abbruch vor dem Start.
  • Wenn eine Instanz vor dem Start aktualisiert wird, wird das nicht als neue Einplanung betrachtet. Deshalb wird für die alte, überschriebene Version nicht WorkItemFinished aufgerufen. Das ist die einzige Konstellation, in der WorkItemFinished nicht für jede technische Instanz des Work-Items aufgerufen wird.
  • Jede Instanz endet immer in einem finalen Status oder mit einem Neustart.

Laufzeitüberwachung

Methode Run

Sobald ein laufendes Work-Items die maximale Laufzeit überschreiten hat oder aber die Anwendung gerade neu gestartet werden soll, bekommt es asynchron das Signal WorkItemShouldFinish und der Status wechselt auf CancellingBySystem (Zeitüberschreitung bzw. ShutdownRequest (Neustart).
Auf dieses Signal kann mit einer Frist von standardmäßig 1 Minute reagieret werden, indem es sich selbst beendet (Methode Run kehrt zurück. Der Status wechselt dann auf TimeOut. Standardmäßig wird die Implementierung von WorkItemFinished sie daraufhin MaxNumberOfRestarts mal neu einplanen. In letzterem Fall wechselt der Status auf TimeoutRetry.

Reagieren ein Work-Item nicht in der gesetzten Frist, wird der Worker Thread hart gekillt, indem eine ThreadAbortException injiziert wird. Der Status des Work-Items wird danach auf Killed gesetzt. Dieser Zustand sollte auf jeden Fall vermieden werden, da er den Datenbestand unter Umständen in einem inkonsistenten Zustand zurücklassen kann.
Die Methode WorkItemFinished wird aber dennoch noch aufgerufen.

Methode WorkItemFinished

Die Laufzeit dieser Methode ist auf 1 Minute begrenzt. Wird diese Zeit überschritten, wird der Prozess hart gekillt, indem eine ThreadAbortException injiziert wird. Der Vorgang wird im Server-Log protokolliert und, falls aktiviert, auch im Anwendungs-Log des Prozesses. Es erfolgt kein zweiter Versuch, und das Work-Item verbleibt in dem finalen Status ohne Nachfolger..