Udostępnij za pośrednictwem


Wywołania procedury asynchronicznej

Wywołanie procedury asynchronicznej (APC) to funkcja wykonywana asynchronicznie w kontekście określonego wątku. Gdy element APC jest w kolejce do wątku, system wystawia przerwanie działania oprogramowania. Przy następnym zaplanowaniu wątku zostanie uruchomiona funkcja APC. APC wygenerowany przez system jest nazywany trybu jądra APC. APC wygenerowany przez aplikację jest nazywany tryb użytkownika APC. Aby można było uruchomić APC w trybie użytkownika, wątek musi być w stanie alertów.

Każdy wątek ma własną kolejkę APC. Aplikacja kolejkuje element APC do wątku przez wywołanie funkcji QueueUserAPC. Wątek wywołujący określa adres funkcji APC w wywołaniu QueueUserAPC. Kolejkowanie APC jest żądaniem, aby wątek wywołał funkcję APC.

Gdy element APC w trybie użytkownika jest kolejkowany, wątek, do którego jest on kolejkowany, nie jest kierowany do wywołania funkcji APC, chyba że jest w stanie alertowalnym. Wątek wprowadza stan alertu, gdy wywołuje SleepEx, SignalObjectAndWait, msgWaitForMultipleObjectsEx, WaitForMultipleObjectsExlub WaitForSingleObjectEx. Jeśli oczekiwanie zostanie spełnione przed kolejką APC, wątek nie jest już w stanie oczekiwania z możliwością alertu, więc funkcja APC nie zostanie wykonana. Jednak APC jest nadal kolejkowany, więc funkcja APC zostanie wykonana, gdy wątek wywołuje inną funkcję oczekiwania z możliwością alertu.

Funkcje ReadFileEx, SetWaitableTimer, SetWaitableTimerExi WriteFileEx są implementowane przy użyciu mechanizmu wywołania zwrotnego powiadomień ukończenia.

Jeśli używasz puli wątków , należy pamiętać, że interfejsy API nie działają, a także inne mechanizmy sygnalizacyjne, ponieważ system kontroluje okres istnienia wątków puli wątków, więc istnieje możliwość zakończenia wątku przed dostarczeniem powiadomienia. Zamiast używać mechanizmu sygnalizacyjnego opartego na protokole APC, takiego jak pfnCompletionRou tine parametru SetWaitableTimer lub SetWaitableTimerEx, użyj obiektu oczekującego, takiego jak czasomierz utworzony za pomocą CreateThreadpoolTimer. W przypadku operacji we/wy użyj obiektu uzupełniania we/wy utworzonego za pomocą CreateThreadpoolIo lub hEventopartego na nakładających się struktury, w której zdarzenie można przekazać do funkcji SetThreadpoolWait.

Wewnętrzne synchronizacji

Po wysłaniu żądania we/wy zostanie przydzielona struktura reprezentująca żądanie. Ta struktura jest nazywana pakietem żądania we/wy (IRP). W przypadku synchronicznego we/wy wątek kompiluje protokół IRP, wysyła go do stosu urządzenia i czeka w jądrze, aby protokół IRP został ukończony. W przypadku asynchronicznego we/wy wątek kompiluje IRP i wysyła go do stosu urządzenia. Stos może natychmiast ukończyć protokół IRP lub może zwrócić stan oczekiwania wskazujący, że żądanie jest w toku. W takim przypadku protokół IRP jest nadal skojarzony z wątkiem, więc zostanie anulowany, jeśli wątek zakończy działanie lub wywoła funkcję, taką jak CancelIo. W międzyczasie wątek może nadal wykonywać inne zadania, podczas gdy stos urządzenia nadal przetwarza protokół IRP.

Istnieje kilka sposobów, na które system może wskazywać, że protokół IRP został ukończony:

  • Zaktualizuj nakładaną się strukturę z wynikiem operacji, aby wątek mógł sondować, aby określić, czy operacja została ukończona.
  • Zasygnalizuj zdarzenie w nakładanej strukturze, aby wątek mógł zostać zsynchronizowany ze zdarzeniem i zostać wybudzony po zakończeniu operacji.
  • Przeprowadź kolejkę protokołu IRP do oczekującego wywołania APC wątku, tak aby wątek wykonał procedurę APC po wprowadzeniu stanu oczekiwania z możliwością alertu i powrócić z operacji oczekiwania ze stanem wskazującym, że wykonano co najmniej jedną procedurę APC.
  • W kolejce IRP do portu ukończenia we/wy, gdzie zostanie wykonany przez następny wątek, który czeka na porcie ukończenia.

Wątki oczekujące na porcie ukończenia we/wy nie czekają w stanie alertu. W związku z tym, jeśli te wątki wystawiają elementy IRPs ustawione jako apcs do wątku, te uzupełnienia IPC nie będą wykonywane w odpowiednim czasie; Wystąpią one tylko wtedy, gdy wątek pobiera żądanie z portu ukończenia we/wy, a następnie następuje wprowadzenie oczekiwania z możliwością alertu.

używanie czasomierza z asynchronicznym wywołaniem procedury