Dela via


Asynkrona proceduranrop

Ett asynkront proceduranrop (APC) är en funktion som körs asynkront i kontexten för en viss tråd. När en APC placeras i kö till en tråd, utfärdar systemet ett programavbrott. Nästa gång tråden schemaläggs körs APC-funktionen. En APC som genereras av systemet kallas för en kernelläges-APC-. En APC som genereras av ett program kallas för en APC-i användarläge. En tråd måste vara i ett aviseringsbart tillstånd för att köra en APC i användarläge.

Varje tråd har en egen APC-kö. Ett program köar en APC till en tråd genom att anropa funktionen QueueUserAPC. Den anropande tråden anger adressen till en APC-funktion i anropet till QueueUserAPC. Köerna för en APC är en begäran om att tråden ska anropa APC-funktionen.

När en användarläges-APC placeras i kö dirigeras inte tråden som den är i kö till för att anropa APC-funktionen om den inte är i ett aviseringsbart tillstånd. En tråd anger ett aviseringsbart tillstånd när den anropar funktionen SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsExeller WaitForSingleObjectEx. Om väntan är uppfylld innan APC placeras i kö är tråden inte längre i ett aviseringsbart väntetillstånd, så APC-funktionen körs inte. APC är dock fortfarande i kö, så APC-funktionen körs när tråden anropar en annan aviseringsbar väntefunktion.

Funktionerna ReadFileEx, SetWaitableTimer, SetWaitableTimerExoch WriteFileEx implementeras med hjälp av en APC som återanropsmekanism för slutförande av meddelanden.

Om du använder en trådpoolbör du tänka på att API:er inte fungerar lika bra som andra signalmekanismer eftersom systemet styr livslängden för trådpooltrådar, så det är möjligt att en tråd avslutas innan meddelandet levereras. I stället för att använda en APC-baserad signalmekanism som pfnCompletionRoutine parametern för SetWaitableTimer eller SetWaitableTimerExanvänder du ett väntebart objekt, till exempel en timer som skapats med CreateThreadpoolTimer. För I/O använder du ett I/O-slutförandeobjekt som skapats med CreateThreadpoolIo eller en hEvent-baserad OVERLAPPED struktur där händelsen kan skickas till funktionen SetThreadpoolWait.

Intern synkronisering

När en I/O-begäran utfärdas allokeras en struktur för att representera begäran. Den här strukturen kallas för I/O-begärandepaket (IRP). Med synkron I/O skapar tråden IRP, skickar den till enhetsstacken och väntar i kerneln på att IRP ska slutföras. Med asynkron I/O skapar tråden IRP och skickar den till enhetsstacken. Stacken kan slutföra IRP omedelbart eller returnera en väntande status som anger att begäran pågår. När detta händer är IRP fortfarande associerat med tråden, så den avbryts om tråden avslutas eller anropar en funktion som CancelIo. Under tiden kan tråden fortsätta att utföra andra uppgifter medan enhetsstacken fortsätter att bearbeta IRP.

Det finns flera sätt som systemet kan indikera att IRP har slutförts:

  • Uppdatera den överlappande strukturen med resultatet av åtgärden så att tråden kan avsöka för att avgöra om åtgärden har slutförts.
  • Signalera händelsen i den överlappande strukturen så att en tråd kan synkroniseras på händelsen och väckas när åtgärden är klar.
  • Köa IRP till trådens väntande APC så att tråden kör APC-rutinen när den går in i ett aviseringsbart väntetillstånd och återgår från vänteåtgärden med status som anger att den körde en eller flera APC-rutiner.
  • Köa IRP till en I/O-slutförandeport, där den körs av nästa tråd som väntar på slutförandeporten.

Trådar som väntar på en I/O-slutförandeport väntar inte i ett aviseringsbart tillstånd. Om dessa trådar utfärdar IRP:er som är inställda på att slutföras som API:er till tråden sker därför inte dessa IPC-slutföranden i tid. de inträffar endast om tråden hämtar en begäran från I/O-slutförandeporten och sedan råkar ange en aviseringsbar väntan.

Använda en väntetidstimer med ett asynkront proceduranrop