非同步程序呼叫

APC) (非同步程序呼叫 是在特定執行緒的內容中以非同步方式執行的函式。 當 APC 排入執行緒佇列時,系統會發出軟體插斷。 下次排程執行緒時,它會執行 APC 函式。 系統所產生的 APC 稱為 核心模式 APC。 應用程式所產生的 APC 稱為 使用者模式 APC。 執行緒必須處於可警示狀態,才能執行使用者模式 APC。

每個執行緒都有自己的 APC 佇列。 應用程式會藉由呼叫 QueueUserAPC 函式,將 APC 排入執行緒。 呼叫執行緒會在 對 QueueUserAPC的呼叫中指定 APC 函式的位址。 APC 的佇列是執行緒呼叫 APC 函式的要求。

將使用者模式 APC 排入佇列時,除非其處於可警示狀態,否則不會將其排入佇列的執行緒導向至呼叫 APC 函式。 當執行緒呼叫 SleepExSignalObjectAndWaitMsgWaitForMultipleObjectsExWaitForMultipleObjectsExWaitForSingleObjectEx 函式時,執行緒會進入可警示的狀態。 如果在 APC 排入佇列之前滿足等候,執行緒就不會再處於可警示的等候狀態,因此不會執行 APC 函式。 不過,APC 仍會排入佇列,因此當執行緒呼叫另一個可警示的等候函式時,將會執行 APC 函式。

ReadFileExSetWaitableTimerSetWaitableTimerExWriteFileEx函式是使用 APC 作為完成通知回呼機制來實作。

如果您使用 執行緒集區,請注意,APC 無法運作和其他訊號機制,因為系統控制執行緒集區執行緒的存留期,因此執行緒可以在傳遞通知之前終止。 不使用以 APC 為基礎的訊號機制,例如SetWaitableTimer 或 SetWaitableTimerExpfnCompletionRoutine參數,而是使用可等候的物件,例如使用CreateThreadpoolTimer建立的計時器。 針對 I/O,請使用使用 CreateThreadpoolIo 所建立的 I/O 完成物件,或以 hEvent為基礎的 OVERLAPPED 結構,其中事件可以傳遞至 SetThreadpoolWait 函式。

同步處理內部

發出 I/O 要求時,會配置 結構來表示要求。 此結構稱為 I/O 要求封包 (IRP) 。 使用同步 I/O,執行緒會建置 IRP、將它傳送至裝置堆疊,並在核心中等候 IRP 完成。 使用非同步 I/O,執行緒會建置 IRP,並將其傳送至裝置堆疊。 堆疊可能會立即完成 IRP,或者可能會傳回擱置狀態,指出要求正在進行中。 發生這種情況時,IRP 仍然與執行緒相關聯,因此如果執行緒終止或呼叫 CancelIo之類的函式,就會取消它。 同時,執行緒可以在裝置堆疊繼續處理 IRP 時繼續執行其他工作。

系統有數種方式可以指出 IRP 已完成:

  • 使用作業的結果更新重迭結構,讓執行緒可以輪詢以判斷作業是否已完成。
  • 發出重迭結構中的事件訊號,讓執行緒可以在事件上同步處理,並在作業完成時喚醒。
  • 將 IRP 排入執行緒的擱置 APC,讓執行緒在進入可警示的等候狀態時執行 APC 常式,並從等候作業傳回,狀態表示它已執行一或多個 APC 常式。
  • 將 IRP 排入 I/O 完成埠,該埠將由等候完成埠的下一個執行緒執行。

等候 I/O 完成埠的執行緒不會處於可警示狀態。 因此,如果這些執行緒發出已設定為 DC 完成的 IRP 至執行緒,這些 IPC 完成將不會及時發生;只有線上程從 I/O 完成埠挑選要求,然後進入可警示等候時,才會發生。

搭配非同步程序呼叫使用可等候計時器