Wait-Funktionen

Wartefunktionen ermöglichen es einem Thread, seine eigene Ausführung zu blockieren. Die Wartefunktionen werden erst zurückgegeben, wenn die angegebenen Kriterien erfüllt sind. Der Typ der Wartefunktion bestimmt den Satz der verwendeten Kriterien. Wenn eine Wartefunktion aufgerufen wird, überprüft sie, ob die Wartekriterien erfüllt wurden. Wenn die Kriterien nicht erfüllt wurden, wechselt der aufrufende Thread in den Wartezustand, bis die Bedingungen der Wartekriterien erfüllt sind oder das angegebene Timeoutintervall verstrichen ist.

Wartefunktionen für ein einzelnes Objekt

Die Funktionen SignalObjectAndWait, WaitForSingleObject und WaitForSingleObjectEx erfordern ein Handle für ein Synchronisierungsobjekt. Diese Funktionen werden zurückgegeben, wenn eine der folgenden Aktionen auftritt:

  • Das angegebene Objekt befindet sich im signalierten Zustand.
  • Das Timeoutintervall verfällt. Das Timeoutintervall kann auf INFINITE festgelegt werden, um anzugeben, dass für die Wartezeit kein Timeout ausgeführt wird.

Die SignalObjectAndWait-Funktion ermöglicht es dem aufrufenden Thread, den Status eines Objekts auf signalisiert festzulegen und zu warten, bis der Status eines anderen Objekts auf signalisiert festgelegt wird.

Wartefunktionen mit mehreren Objekten

Die Funktionen WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjects und MsgWaitForMultipleObjectsEx ermöglichen es dem aufrufenden Thread, ein Array anzugeben, das mindestens ein Synchronisierungsobjekthandles enthält. Diese Funktionen werden zurückgegeben, wenn eine der folgenden Aktionen auftritt:

  • Der Zustand eines der angegebenen Objekte wird auf signalisiert festgelegt, oder die Zustände aller Objekte wurden auf signalisiert festgelegt. Sie steuern, ob einer oder alle Zustände im Funktionsaufruf verwendet werden.
  • Das Timeoutintervall verfällt. Das Timeoutintervall kann auf INFINITE festgelegt werden, um anzugeben, dass für die Wartezeit kein Timeout ausgeführt wird.

Mit den Funktionen MsgWaitForMultipleObjects und MsgWaitForMultipleObjectsEx können Sie Eingabeereignisobjekte im Objekthandlearray angeben. Dies erfolgt, wenn Sie den Typ der Eingabe angeben, auf die in der Eingabewarteschlange des Threads gewartet werden soll. Beispielsweise könnte ein Thread MsgWaitForMultipleObjects verwenden, um seine Ausführung zu blockieren, bis der Status eines angegebenen Objekts auf signalisiert festgelegt wurde und mauseingaben in der Eingabewarteschlange des Threads verfügbar sind. Der Thread kann die Funktion GetMessage , PeekMessageA oder PeekMessageW verwenden, um die Eingabe abzurufen.

Wenn sie darauf warten, dass die Zustände aller Objekte auf signalisiert festgelegt werden, ändern diese Funktionen mit mehreren Objekten die Zustände der angegebenen Objekte erst, wenn die Zustände aller Objekte signalisiert wurden. Beispielsweise kann der Zustand eines Mutex-Objekts signalisiert werden, aber der aufrufende Thread erhält erst dann den Besitz, wenn die Zustände der anderen im Array angegebenen Objekte ebenfalls auf signalisiert wurden. In der Zwischenzeit kann ein anderer Thread den Besitz des Mutex-Objekts erhalten, wodurch sein Zustand auf nicht signalisiert festgelegt wird.

Wenn sie darauf warten, dass der Status eines einzelnen Objekts auf signalisiert wird, überprüfen diese Funktionen mit mehreren Objekten die Handles im Array, beginnend mit Index 0, bis eines der Objekte signalisiert wird. Wenn mehrere Objekte signalisiert werden, gibt die Funktion den Index des ersten Handles in dem Array zurück, dessen Objekt signalisiert wurde.

Warnbare Wartefunktionen

Die Funktionen MsgWaitForMultipleObjectsEx, SignalObjectAndWait, WaitForMultipleObjectsEx und WaitForSingleObjectEx unterscheiden sich von den anderen Wartefunktionen darin, dass sie optional einen warnbaren Wartevorgang ausführen können. In einem warnbaren Wartevorgang kann die Funktion zurückgeben, wenn die angegebenen Bedingungen erfüllt sind, aber sie kann auch zurückgeben, wenn das System eine E/A-Abschlussroutine oder einen APC für die Ausführung durch den wartenden Thread in die Warteschlange stellt. Weitere Informationen zu warnbaren Wartevorgängen und E/A-Vervollständigungsroutinen finden Sie unter Synchronisierung und überlappende Eingabe und Ausgabe. Weitere Informationen zu APCs finden Sie unter Asynchrone Prozeduraufrufe.

Registrierte Wartefunktionen

Die RegisterWaitForSingleObject-Funktion unterscheidet sich von den anderen Wartefunktionen darin, dass der Wartevorgang von einem Thread aus dem Threadpool ausgeführt wird. Wenn die angegebenen Bedingungen erfüllt sind, wird die Rückruffunktion von einem Workerthread aus dem Threadpool ausgeführt.

Standardmäßig ist ein registrierter Wartevorgang ein Mehrfachwartevorgang. Das System setzt den Timer jedes Mal zurück, wenn das Ereignis signalisiert wird (oder das Timeoutintervall verstrichen ist), bis Sie die UnregisterWaitEx-Funktion aufrufen, um den Vorgang abzubrechen. Um anzugeben, dass ein Wartevorgang nur einmal ausgeführt werden soll, legen Sie den dwFlags-Parameter von RegisterWaitForSingleObject auf WT_EXECUTEONLYONCE fest.

Wenn der Thread Funktionen aufruft, die APCs verwenden, legen Sie den dwFlags-Parameter von RegisterWaitForSingleObject auf WT_EXECUTEINPERSISTENTTHREAD fest.

Warten auf eine Adresse

Ein Thread kann die WaitOnAddress-Funktion verwenden, um darauf zu warten, dass sich der Wert einer Zieladresse von einem unerwünschten Wert in einen anderen Wert ändert. Dadurch können Threads darauf warten, dass sich ein Wert ändert, ohne sich drehen oder die Synchronisierungsprobleme behandeln zu müssen, die auftreten können, wenn der Thread einen unerwünschten Wert erfasst, sich der Wert jedoch ändert, bevor der Thread warten kann.

WaitOnAddress gibt zurück, wenn Code, der den Zielwert ändert, die Änderung signalisiert, indem WakeByAddressSingle aufgerufen wird , um einen einzelnen wartenden Thread zu reaktivieren, oder WakeByAddressAll , um alle wartenden Threads zu reaktivieren. Wenn mit WaitOnAddress ein Timeoutintervall angegeben wird und kein Thread eine Reaktivierungsfunktion aufruft, gibt die Funktion zurück, wenn das Timeoutintervall verstrichen ist. Wenn kein Timeoutintervall angegeben wird, wartet der Thread unbegrenzt.

Wartefunktionen und Timeoutintervalle

Die Genauigkeit des angegebenen Timeoutintervalls hängt von der Auflösung der Systemuhr ab. Die Systemuhr "tickt" mit einer konstanten Rate. Wenn das Timeoutintervall kleiner als die Auflösung der Systemuhr ist, kann ein Timeout der Wartezeit unter der angegebenen Zeitdauer auftreten. Wenn das Timeoutintervall größer als ein Tick, aber kleiner als zwei ist, kann die Wartezeit zwischen einem und zwei Teilstrichen erfolgen usw.

Um die Genauigkeit des Timeoutintervalls für die Wartefunktionen zu erhöhen, rufen Sie die timeGetDevCaps-Funktion auf, um die unterstützte minimale Timerauflösung zu bestimmen, und die timeBeginPeriod-Funktion , um die Timerauflösung auf ihr Minimum festzulegen. Gehen Sie beim Aufrufen von timeBeginPeriod vorsichtig vor, da sich häufige Anrufe erheblich auf die Systemuhr, die Systemenergienutzung und den Scheduler auswirken können. Wenn Sie timeBeginPeriod aufrufen, rufen Sie es einmal früh in der Anwendung auf, und achten Sie darauf, dass Sie die timeEndPeriod-Funktion ganz am Ende der Anwendung aufrufen.

Wartefunktionen und Synchronisierungsobjekte

Die Wartefunktionen können den Status einiger Typen von Synchronisierungsobjekten ändern. Die Änderung erfolgt nur für das Objekt oder die Objekte, deren signalisierter Zustand dazu geführt hat, dass die Funktion zurückgegeben wurde. Wait-Funktionen können den Status von Synchronisierungsobjekten wie folgt ändern:

  • Die Anzahl eines Semaphorobjekts nimmt um eins ab, und der Zustand des Semaphors wird auf nicht signalisiert festgelegt, wenn die Anzahl null ist.
  • Die Zustände von Mutex-, Auto-Reset-Ereignis- und Änderungsbenachrichtigungsobjekten sind auf nicht signalisiert festgelegt.
  • Der Status eines Synchronisierungszeitgebers ist auf nicht signalisiert festgelegt.
  • Die Zustände von Manuell zurückgesetzten Ereignissen, Timer für manuelles Zurücksetzen, Prozess, Thread und Konsoleneingabeobjekte werden von einer Wartefunktion nicht beeinflusst.

Warten von Funktionen und Erstellen von Fenstern

Sie müssen vorsichtig sein, wenn Sie die Wartefunktionen und den Code verwenden, der direkt oder indirekt Fenster erstellt. Wenn ein Thread Fenster erstellt, muss er Meldungen verarbeiten. Nachrichtenübertragungen werden an alle Fenster im System gesendet. Wenn Sie über einen Thread verfügen, der eine Wartefunktion ohne Timeoutintervall verwendet, wird das System deadlockt. Zwei Beispiele für Code, der indirekt Fenster erstellt, sind DDE und die CoInitialize-Funktion . Wenn Sie also über einen Thread verfügen, der Fenster erstellt, verwenden Sie MsgWaitForMultipleObjects oder MsgWaitForMultipleObjectsEx anstelle der anderen Wait-Funktionen.