Teilen über


Asynchrone Prozeduraufrufe

Ein asynchroner Prozeduraufruf (APC) ist eine Funktion, die asynchron im Kontext eines bestimmten Threads ausgeführt wird. Wenn ein APC an einen Thread in die Warteschlange gestellt wird, gibt das System eine Softwareunterbrechung aus. Wenn der Thread das nächste Mal geplant wird, wird die APC-Funktion ausgeführt. Ein vom System generierter APC wird als Kernelmodus-APC-bezeichnet. Ein von einer Anwendung generierter APC wird als Benutzermodus-APC-bezeichnet. Ein Thread muss sich in einem warnungsfähigen Zustand befinden, um einen Benutzermodus-APC auszuführen.

Jeder Thread verfügt über eine eigene APC-Warteschlange. Eine Anwendung stellt einen APC in eine Warteschlange in einen Thread ein, indem die QueueUserAPC--Funktion aufgerufen wird. Der aufrufende Thread gibt die Adresse einer APC-Funktion im Aufruf von QueueUserAPC-an. Die Warteschlange eines APC ist eine Anforderung für den Thread, die APC-Funktion aufzurufen.

Wenn ein Benutzermodus-APC in die Warteschlange gestellt wird, wird der Thread, an den er in die Warteschlange gestellt wird, nicht angewiesen, die APC-Funktion aufzurufen, es sei denn, er befindet sich in einem warnungsfähigen Zustand. Ein Thread wechselt in einen warnbaren Zustand, wenn er den SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsExoder WaitForSingleObjectEx-Funktion aufruft. Wenn die Wartezeit erfüllt ist, bevor der APC in die Warteschlange gestellt wird, befindet sich der Thread nicht mehr in einem warnbaren Wartezustand, sodass die APC-Funktion nicht ausgeführt wird. Das APC wird jedoch weiterhin in die Warteschlange gestellt, sodass die APC-Funktion ausgeführt wird, wenn der Thread eine weitere warnbare Wartefunktion aufruft.

Die ReadFileEx, SetWaitableTimer-, SetWaitableTimerEx-und WriteFileEx- Funktionen werden mithilfe eines APC als Abschlussbenachrichtigungsrückrufmechanismus implementiert.

Wenn Sie einen Threadpoolverwenden, beachten Sie, dass APCs nicht genauso gut funktionieren wie andere Signalmechanismen, da das System die Lebensdauer von Threadpoolthreads steuert, sodass es möglich ist, dass ein Thread beendet werden kann, bevor die Benachrichtigung übermittelt wird. Anstatt einen APC-basierten Signalisierungsmechanismus wie die pfnCompletionRoutine Parameter von SetWaitableTimer oder SetWaitableTimerExzu verwenden, verwenden Sie ein mit CreateThreadpoolTimererstelltes Zeitgeberobjekt. Verwenden Sie für E/A ein mit CreateThreadpoolIo erstelltes E/A-Vervollständigungsobjekt oder eine hEvent--basierte OVERLAPPED--Struktur, in der das Ereignis an die SetThreadpoolWait--Funktion übergeben werden kann.

Interne Synchronisierung

Wenn eine E/A-Anforderung ausgestellt wird, wird eine Struktur zugewiesen, um die Anforderung darzustellen. Diese Struktur wird als E/A-Anforderungspaket (IRP) bezeichnet. Bei synchroner E/A erstellt der Thread das IRP, sendet es an den Gerätestapel und wartet im Kernel, bis das IRP abgeschlossen ist. Bei asynchroner E/A erstellt der Thread das IRP und sendet ihn an den Gerätestapel. Der Stapel kann das IRP sofort abschließen, oder er gibt einen ausstehenden Status zurück, der angibt, dass die Anforderung ausgeführt wird. In diesem Fall wird der IRP weiterhin dem Thread zugeordnet, sodass er abgebrochen wird, wenn der Thread eine Funktion wie CancelIobeendet oder aufruft. In der Zwischenzeit kann der Thread weiterhin andere Aufgaben ausführen, während der Gerätestapel das IRP weiter verarbeitet.

Es gibt mehrere Möglichkeiten, wie das System angeben kann, dass das IRP abgeschlossen ist:

  • Aktualisieren Sie die überlappende Struktur mit dem Ergebnis des Vorgangs, damit der Thread abfragen kann, um festzustellen, ob der Vorgang abgeschlossen wurde.
  • Signalisieren Sie das Ereignis in der überlappenden Struktur, damit ein Thread für das Ereignis synchronisiert werden kann und nach Abschluss des Vorgangs wach werden kann.
  • Warteschlange das IRP an das ausstehende APC des Threads, sodass der Thread die APC-Routine ausführt, wenn er in einen warnbaren Wartezustand wechselt und vom Wartevorgang mit einem Status zurückgegeben wird, der angibt, dass er eine oder mehrere APC-Routinen ausgeführt hat.
  • Warteschlangen Sie den IRP an einen E/A-Abschlussport, an dem er vom nächsten Thread ausgeführt wird, der auf den Abschlussport wartet.

Threads, die auf einen E/A-Abschlussport warten, warten nicht in einem warnungsfähigen Zustand. Wenn diese Threads IRPs ausgeben, die als APCs für den Thread festgelegt sind, treten diese IPC-Fertigstellungen daher nicht rechtzeitig auf; sie treten nur auf, wenn der Thread eine Anforderung vom E/A-Vervollständigungsport empfängt und dann eine warnbare Wartezeit eingibt.

Verwenden eines zeitfähigen Zeitgebers mit einem asynchronen Prozeduraufruf