Kontexte

In diesem Dokument wird die Rolle von Kontexten in der Concurrency Runtime beschrieben. Der an einen Planer angefügte Thread wird als Ausführungskontext oder einfach als Kontext bezeichnet. Mit der Concurrency::wait-Funktion und der Concurrency::Context-Klasse können Sie das Verhalten von Kontexten steuern. Mit der wait-Funktion können Sie den aktuellen Kontext für einen bestimmten Zeitraum unterbrechen. Mit der Context-Klasse können Sie die Kontrolle über Kontexte verbessern und diese leichter blockieren (bzw. die Blockierung aufzuheben) und zurückzuhalten und den aktuellen Kontext überzeichnen.

Tipp

Die Concurrency Runtime stellt einen Standardplaner bereit. Es ist daher nicht erforderlich, einen Planer in der Anwendung zu erstellen. Der Taskplaner ermöglicht eine genauere Steuerung der Leistung von Anwendungen. Aus diesem Grund wird empfohlen, mit der Parallel Patterns Library (PPL) oder der Asynchronous Agents Library zu beginnen, wenn Sie noch nicht mit der Concurrency Runtime vertraut sind.

Die wait-Funktion

Mit der Concurrency::wait-Funktion können Sie den aktuellen Kontext für eine angegebene Anzahl an Millisekunden kooperativ zurückhalten. Der Zurückhaltungszeitraum wird zur Ausführung anderer Aufgaben genutzt. Nach Ablauf des angegebenen Zeitraums plant die Runtime die Kontextausführung neu. Aus diesem Grund kann die Unterbrechung des aktuellen Kontexts mit der wait-Funktion länger dauern als mit dem Wert für den milliseconds-Parameter angegeben.

Bei der Übergabe von 0 (null) für den milliseconds-Parameter unterbricht die Runtime den aktuellen Kontext, bis die Verarbeitung für alle anderen aktiven Kontexte ermöglicht wurde. Hiermit können Sie eine Aufgabe zugunsten von allen anderen aktiven Aufgaben zurückhalten.

Beispiel

Ein Beispiel, in dem der aktuelle Kontext mit der wait-Funktion zurückgehalten wird, damit andere Kontexte ausgeführt werden können, finden Sie unter Gewusst wie: Beeinflussen der Ausführungsreihenfolge mithilfe von Zeitplangruppen.

Die Context-Klasse

Die Concurrency::Context-Klasse stellt eine Programmierabstraktion für einen Ausführungskontext sowie zwei weitere wichtige Funktionen bereit: die Fähigkeit, den aktuellen Kontext kooperativ zu blockieren (bzw. die Blockierung aufzuheben) und zurückzuhalten und die Fähigkeit, den aktuellen Kontext zu überzeichnen.

Kooperative Blockierung

Mit der Context-Klasse können Sie den aktuellen Ausführungskontext blockieren oder zurückhalten. Das Blockieren oder Zurückhalten ist nützlich, wenn der aktuelle Kontext nicht fortfahren kann, da eine Ressource nicht verfügbar ist.

Mit der Concurrency::Context::Block-Methode blockieren Sie den aktuellen Kontext. Die Verarbeitungsressourcen des blockierten Kontexts werden zurückgehalten, sodass die Runtime andere Aufgaben ausführen kann. Mit der Concurrency::Context::Unblock-Methode heben Sie die Blockierung eines blockierten Kontexts auf. Die Context::Unblock-Methode muss aus einem anderen Kontext aufgerufen werden als die Context::Block-Methode. Andernfalls löst die Runtime den Fehler Concurrency::context_self_unblock aus.

Um einen Kontext kooperativ zu blockieren und die Blockierung aufzuheben, rufen Sie in der Regel Concurrency::Context::CurrentContext auf. Damit wird ein Zeiger auf das Context-Objekt abgerufen, das mit dem aktuellen Thread verknüpft ist, und das Ergebnis wird gespeichert. Mit der Context::Block-Methode können Sie den aktuellen Kontext blockieren. Um die Blockierung aufzuheben, rufen Sie zu einem späteren Zeitpunkt die Context::Unblock-Methode aus einem anderen Kontext auf.

Die Aufrufe der Context::Block-Methode und der Context::Unblock-Methode müssen immer paarweise erfolgen. Die Runtime löst Concurrency::context_unblock_unbalanced aus, wenn die Context::Block-Methode oder die Context::Unblock-Methode ohne einen entsprechenden Aufruf der jeweils anderen Methode mehrmals hintereinander aufgerufen wird. Sie müssen jedoch die Context::Block-Methode nicht zwingend vor der Context::Unblock-Methode aufrufen. Wenn aus einem Kontext beispielsweise die Context::Unblock-Methode aufgerufen wird, bevor aus einem anderen Kontext die Context::Block-Methode aufgerufen wird, erfolgt keine Blockierung des Kontexts.

Mit der Concurrency::Context::Yield-Methode wird die Ausführung zurückgehalten, sodass die Runtime andere Aufgaben ausführen und dann die Ausführung des Kontexts neu planen kann. Wenn Sie die Context::Block-Methode aufrufen, wird der Kontext von der Laufzeit nicht neu geplant.

Beispiel

Ein Beispiel, in dem die Methoden Context::Block, Context::Unblock und Context::Yield verwendet werden, um eine kooperative Semaphorenklasse zu implementieren, finden Sie unter Gewusst wie: Implementieren einer kooperativen Semaphore mithilfe der Context-Klasse.

Überzeichnung

Die vom Standardplaner erstellte Anzahl an Threads stimmt mit der Anzahl der verfügbaren Hardwarethreads überein. Mithilfe der Überzeichnung können Sie zusätzliche Threads für einen gegebenen Hardwarethread erstellen.

Für rechenintensive Vorgänge ist die Überzeichnung nicht geeignet, da sie zusätzlichen Aufwand erfordert. Bei Aufgaben mit einer hohen Latenz, wie z. B. das Lesen von Daten von der Festplatte oder von einer Netzwerkverbindung, lässt sich die allgemeine Effizienz einiger Anwendungen mit der Überzeichnung jedoch durchaus verbessern.

Tipp

Aktivieren Sie die Überzeichnung nur in einem nicht-UMS-Thread, der von der Concurrency Runtime erstellt wurde. Die Überzeichnung hat keine Auswirkungen, wenn sie in einem Thread aufgerufen wird, der nicht von der Runtime (einschließlich des Hauptthreads) erstellt wurde. Außerdem hat die Überzeichnung keine Auswirkungen, wenn sie in einem Kontext aufgerufen wird, der UMS-Threads verwendet, um Aufgaben zu planen, da der Planer mithilfe von UMS-Threads vollständig auf Ressourcen zugreifen kann, auch wenn gerade blockierende Vorgänge ausgeführt werden.

Um die Überzeichnung für den aktuellen Kontext zu aktivieren, rufen Sie die Concurrency::Context::Oversubscribe-Methode auf, wobei der _BeginOversubscription-Parameter auf true festgelegt sein muss. Wenn Sie die Überzeichnung für einen von der Concurrency Runtime erstellten Thread aktivieren, erstellt die Runtime einen zusätzlichen Thread. Nachdem alle Aufgaben, die Überzeichnung erfordern, beendet wurden, rufen Sie die Context::Oversubscribe-Methode mit der _BeginOversubscription-Parametereinstellung false auf.

Sie können die Überzeichnung aus dem aktuellen Kontext mehrmals aktivieren, müssen die Überzeichnung aber immer genauso oft deaktivieren. Überzeichnung kann auch geschachtelt werden. Das heißt, der Kontext einer Aufgabe, die von einer anderen Aufgabe erstellt wird, kann auch überzeichnet werden. Wenn jedoch die geschachtelte und die übergeordnete Aufgabe dem gleichen Kontext zugeordnet sind, wird nur beim Aufruf von Context::Oversubscribe auf der jeweils obersten Ebene ein zusätzlicher Thread erstellt.

Tipp

Wenn Sie die Überzeichnung deaktivieren, bevor sie aktiviert wurde, löst die Runtime Concurrency::invalid_oversubscribe_operation aus.

Beispiel

Ein Beispiel, in dem die Überzeichnung zum Kompensieren der Latenz beim Lesen von Daten von einer Netzwerkverbindung verwendet wird, finden Sie unter Gewusst wie: Verwenden der Überzeichnung zum Kompensieren der Latenz.

Siehe auch

Aufgaben

Gewusst wie: Verwenden der Überzeichnung zum Kompensieren der Latenz

Konzepte

Taskplaner (Concurrency Runtime)

Weitere Ressourcen

Gewusst wie: Beeinflussen der Ausführungsreihenfolge mithilfe von Zeitplangruppen

Gewusst wie: Implementieren einer kooperativen Semaphore mithilfe der Context-Klasse

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Juli 2010

Inhalt neu strukturiert.

Informationsergänzung.