Die Task-Klasse repräsentiert eine CPU-bound oder eine IO-bound Aufgabe. Dieser Blog erklärt die wichtigsten Aspekten der Task-Klasse.
Zusammen mit TPL (Task Parallel Library) wurde mit .NET Framework 4.0 die Task-Klasse eingeführt. Im Kontext von TPL ist ein Task eine Abstraktion einer CPU-bound Aufgabe die durch den Thread Scheduler an einen Thread zugewiesen wird. Das kann ein Thread aus dem Threadpool sein oder ein eigener Thread (TaskCreationOptions.LongRunning).
In .NET Framework 4.5 wurde das async\await-Model für IO-bound Aufgaben eingeführt. Weil die Task-Klasse schon viele Eigenschaften hatte die es für async\await ebenfalls brauchte, hat Microsoft entschieden die Klasse zu erweitern und für async\await einzusetzen. Im Kontext von async\await wird ein Task nicht einem Thread zugewiesen. Es wird höchstens der Code nach dem await auf einem Threadpool Thread ausgeführt wenn ConfigureAwait(false) spezifiziert wurde. Doch dazu mehr in einem späteren Blog.
Es gibt also zwei Typen von Tasks die beide mit dem gleichen Konstrukt abgedeckt werden:
Delegate Tasks (code-based tasks): parallele Programmierung
Promise Tasks (event-based tasks): asynchrone Programmierung
-> EAP – Model (Event-based Asynchronous Pattern)
-> APM – Model (Asynchronous Programming Model)
-> async\await
In dieser Blog-Serie wird nur Statischer Task Parallelismus behandelt und die asynchrone Programmierung.
Ein cold Task ist ein Task der zwar kreiert wurde (z.B. mit ‚new Task()‘) aber noch nicht durch den Task Scheduler gestartet wurde. Ein hot Task läuft bereits.
Ein Task mit Status RanToCompletion kann nicht mehr neu gestartet werden.
Die Klasse Task repräsentiert eine Aufgabe die keinen Rückgabewert hat, Task<T> repräsentiert eine Aufgabe mit Rückgabewert von Typ T.
Sobald der Task kreiert wurde, kann man den aktuellen Status auslesen in der Eigenschaft Status.
Separat gibt es noch die Eigenschaften IsCompleted, IsCanceled und IsFaulted.
Die folgende Tabelle erklärt die Zusammenhänge:
Ein delegate Task kann folgende Zustände haben:
Im Normalfall wird ein Task mit Task.Run() gestartet. Rückgabe davon ist ein ‚hot Task‘, also einen Task mit Status Running. Je nach Laufzeitereignissen endet der Task mit RanToCompletion, Faulted oder Canceled. Der Task ist gekoppelt an einen Thread während den Zuständen Running und WaitingForChildrenToComplete.
Wenn eine IO-bound Aktion am warten ist (z.B. während eines HTTP download) wird kein Code ausgeführt (es gibt kein Thread). Beim promise Task fehlen deshalb die Zustände WaitingToRun und Running. Verwirrend: Es gibt trotzdem den Zustand RanToCompletion, obwohl der Task gar nie Running war.
Ein promise Task wird immer ‚hot‘ kreiert, was heisst, dass die Operation in Bearbeitung ist. Der Zustand WaitingForActivation sollte eigentlich „InProgress“ heissen.
Die Eigenschaft Result enthält den Rückgabewert von Task<T>. Der Wert steht erst zur Verfügung, wenn der Task den Status RanToCompletion hat.
Eventuelle Exceptions werden in der Exception Eigenschaft vom Task Objekt gespeichert. Die Information steht erst zur Verfügung, wenn der Task den Status Faulted oder Canceled hat. Weil Tasks verschachtelt sein können, wird dazu der Typ AggregateException verwendet.
Folgende Eigenschaften enthalten die Ausnahmeinformationen:
Um die Hierarchie der Innerexceptions flach zu schlagen, gibt es den Aufruf ‚Flatten‘. Folgendes Beispiel erstellt eine Liste mit Ausnahmen und filtert eventuelle OperationCanceledExceptions herraus (dazu später mehr).
List<Exception> exceptions = aggregateException.Flatten().InnerExceptions.Where(e => !(e is OperationCanceledException)).ToList();
Das Exception-Handling für delegate und promise Tasks ist unterschiedlich und wird in den nachfolgenden Blogs erklärt.
Nächstes Mal werden delegate Tasks mit TPL ausführlich behandelt. Wir schauen uns das Erstellen der Tasks, Cancellation und Exception Hanlding an.
[…] ← Vorige Post Nächster Post → […]
[…] im vorigen Blog C# Concurrency Teil 7: Die Task-Klasse schon erklärt wurde ist ein Task im Kontext von TPL eine Abstraktion einer CPU-bound Aufgabe die […]
[…] ← Vorige Post Nächster Post → […]