en / de
Expertisen
Methoden
Dienstleistungen
Referenzen
Jobs & Karriere
Firma
Technologie-Trends TechCast WebCast TechBlog News Events Academy

C# Concurrency Teil 7: Die Task-Klasse

Die Task-Klasse repräsentiert eine CPU-bound oder eine IO-bound Aufgabe. Dieser Blog erklärt die wichtigsten Aspekten der Task-Klasse.

Zwei Task Typen

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:

  1. Delegate Tasks (code-based tasks): für parallele CPU-bound Aufgaben. Dieser Task-Typ repräsentiert Code der parallel ausgeführt werden soll. Das passiert immer auf einem eigenen Thread.
  2. Promise Tasks (event-based tasks): für asynchrone IO-bound Aufgaben. Dieser Task-Typ repräsentiert ein Event oder Signal worauf gewartet werden muss. Der Code vor dem await wird auf dem aufrufenden Thread ausgeführt. Während des Wartens ist kein Thread aktiv und der Code nach dem await wird entweder auf dem aufrufenden Thread oder einen Threadpool Thread ausgeführt.

Einordnung der Lösungstechnologien

Delegate Tasks (code-based tasks): parallele Programmierung

  1. Data Parallelismus
    -> Parallel-Klasse
    -> PLINQ
  2. Task Parallelismus
    1. Statischer Task Parallelismus
      -> Task.Run & Task.Factory.StartNew()
    2. Dynamischer Task Parallelismus
      -> new Task()

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.

Diverses

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 Task-Klasse

Die Klasse Task repräsentiert eine Aufgabe die keinen Rückgabewert hat, Task<T> repräsentiert eine Aufgabe mit Rückgabewert von Typ T.

Zustand eines Tasks

Sobald der Task kreiert wurde, kann man den aktuellen Status auslesen in der Eigenschaft Status.

Task Eigenschaft Status

Separat gibt es noch die Eigenschaften IsCompleted, IsCanceled und IsFaulted.
Die folgende Tabelle erklärt die Zusammenhänge:

Task Eigenschaften IsCompleted, IsCanceled und IsFaulted

Zustand eines delegate Tasks

Ein delegate Task kann folgende Zustände haben:

Zustände eines delegate Tasks

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.

Zustand eines promise Tasks

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 Zustände eines promise Tasks

Result

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.

Exceptions

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.

Follow up

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 →
Kommentare

3 Antworten zu “C# Concurrency Teil 7: Die Task-Klasse”

  1. […] 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 […]

Schreiben Sie einen Kommentar

Ihre E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Newsletter - aktuelle Angebote, exklusive Tipps und spannende Neuigkeiten

 Jetzt anmelden
NACH OBEN
Zur Webcast Übersicht