Aszinkron eljáráshívások
Az aszinkron eljáráshívási (APC) egy függvény, amely aszinkron módon hajt végre egy adott szál kontextusában. Ha egy APC egy szálra vár, a rendszer szoftveres megszakítást ad ki. A szál következő ütemezésekor az APC függvényt fogja futtatni. A rendszer által létrehozott APC-t kernel módú APC-nevezik. Az alkalmazás által létrehozott APC-t felhasználói módú APC-nevezik. A felhasználói módú APC futtatásához a szálnak riasztási állapotban kell lennie.
Minden szál saját APC-üzenetsorsal rendelkezik. Egy alkalmazás a QueueUserAPC függvény meghívásával várólistára állít egy APC-t egy szálra. A hívószál egy APC-függvény címét adja meg a QueueUserAPC hívásában. Az APC-k sorba helyezése a szálnak az APC-függvény meghívására irányuló kérése.
Ha egy felhasználói módú APC várólistára kerül, a folyamat, amelyhez várólistára kerül, nem lesz átirányítva az APC-függvény meghívására, kivéve, ha riasztási állapotban van. A szál riasztási állapotba kerül, amikor meghívja a SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsExvagy WaitForSingleObjectEx függvényt. Ha a várakozás az APC várólistára helyezése előtt teljesül, a szál már nem riasztásos várakozási állapotban van, így az APC-függvény nem lesz végrehajtva. Az APC azonban továbbra is várólistán van, ezért az APC-függvény akkor lesz végrehajtva, amikor a szál egy másik riasztásra alkalmas várakozási függvényt hív meg.
A ReadFileEx, SetWaitableTimer, SetWaitableTimerExés WriteFileEx függvények a befejezési értesítés visszahívási mechanizmusaként APC használatával implementálhatók.
Ha szálkészletet használ, vegye figyelembe, hogy az APC-k nem működnek, valamint más jelátviteli mechanizmusok, mivel a rendszer szabályozza a szálkészlet-szálak élettartamát, ezért lehetséges, hogy egy szál az értesítés kézbesítése előtt leálljon. APC-alapú jelátviteli mechanizmus, például a SetWaitableTimerpfnCompletionRoutine paramétere vagy a SetWaitableTimerExhelyett használjon egy várható objektumot, például egy CreateThreadpoolTimerhasználatával létrehozott időzítőt. I/O esetén használjon CreateThreadpoolIo vagy hEvent-alapú ÁTFEDÉSBEN lévő struktúrát, ahol az esemény átadható a SetThreadpoolWait függvénynek.
Belső szinkronizálás
I/O-kérelem kiadásakor a rendszer egy struktúrát rendel hozzá a kérelem megjelenítéséhez. Ezt a struktúrát I/O-kéréscsomagnak (IRP) nevezzük. Szinkron I/O esetén a szál létrehozza az IRP-t, elküldi azt az eszközveremnek, és megvárja a kernelben, amíg az IRP befejeződik. Az aszinkron I/O-val a szál létrehozza az IRP-t, és elküldi azt az eszközveremnek. Előfordulhat, hogy a verem azonnal befejezi az IRP-t, vagy függőben lévő állapotot ad vissza, amely jelzi, hogy a kérés folyamatban van. Ha ez történik, az IRP továbbra is a szálhoz van társítva, ezért a rendszer megszakítja, ha a szál leáll, vagy meghív egy függvényt, például CancelIo. Addig is a szál más feladatokat is végrehajthat, amíg az eszköz verem továbbra is feldolgozta az IRP-t.
A rendszer többféleképpen jelezheti, hogy az IRP befejeződött:
- Frissítse az átfedésben lévő struktúrát a művelet eredményével, hogy a szál lekérdezhesse, hogy a művelet befejeződött-e.
- Jelezze az eseményt az átfedésben lévő struktúrában, hogy egy szál szinkronizálhassa az eseményt, és a művelet befejezésekor felébredhessenek.
- Az IRP várólistára helyezése a szál függőben lévő APC-jének megfelelően, hogy a szál végrehajtsa az APC-rutint, amikor riasztási várakozási állapotba kerül, és a várakozási műveletből visszatér egy vagy több APC-rutin végrehajtására utaló állapottal.
- Az IRP várólistára helyezése egy I/O-befejezési portra, ahol a következő szál hajtja végre, amely a befejezési porton várakozik.
Az I/O-befejezési porton várakozó szálak nem várakoznak riasztási állapotban. Ezért ha ezek a szálak olyan integrációs modulokat adnak vissza, amelyek a szál API-jaként vannak beállítva, ezek az IPC-befejezések nem fognak időben bekövetkezni; ezek csak akkor fordulnak elő, ha a szál egy kérést kap az I/O-befejezési portról, majd riasztási várakozást ad meg.
Kapcsolódó témakörök