Llamadas a procedimientos asincrónicos

Una llamada a procedimiento asincrónico (APC) es una función que se ejecuta de forma asincrónica en el contexto de un subproceso determinado. Cuando un APC se pone en cola en un subproceso, el sistema emite una interrupción de software. La próxima vez que se programe el subproceso, ejecutará la función APC. Un APC generado por el sistema se denomina APC en modo kernel. Un APC generado por una aplicación se denomina APC en modo de usuario. Un subproceso debe estar en un estado de alerta para ejecutar un APC en modo de usuario.

Cada subproceso tiene su propia cola de APC. Una aplicación pone en cola un APC en un subproceso mediante una llamada a la función QueueUserAPC . El subproceso que llama especifica la dirección de una función de APC en la llamada a QueueUserAPC. La cola de un APC es una solicitud para que el subproceso llame a la función de APC.

Cuando se pone en cola un APC en modo de usuario, el subproceso al que está en cola no se dirige a llamar a la función de APC a menos que esté en estado de alerta. Un subproceso entra en un estado de alerta cuando llama a la función SleepEx, SignalObjectAndWait, MsgWaitForMultipleObjectsEx, WaitForMultipleObjectsEx o WaitForSingleObjectEx . Si se cumple la espera antes de que se pone en cola el APC, el subproceso ya no se encuentra en un estado de espera alertable para que la función de APC no se ejecute. Sin embargo, el APC sigue en cola, por lo que la función de APC se ejecutará cuando el subproceso llame a otra función de espera que se pueda alertar.

Las funciones ReadFileEx, SetWaitableTimer, SetWaitableTimerEx y WriteFileEx se implementan mediante un APC como mecanismo de devolución de llamada de notificación de finalización.

Si usa un grupo de subprocesos, tenga en cuenta que las API no funcionan así como otros mecanismos de señalización porque el sistema controla la duración de los subprocesos del grupo de subprocesos, por lo que es posible que un subproceso finalice antes de que se entregue la notificación. En lugar de usar un mecanismo de señalización basado en APC, como el parámetro pfnCompletionRoutine de SetWaitableTimer o SetWaitableTimerEx, use un objeto esperable como un temporizador creado con CreateThreadpoolTimer. Para E/S, use un objeto de finalización de E/S creado con CreateThreadpoolIo o una estructura SUPERPUESTA basada en hEvent, donde el evento se puede pasar a la función SetThreadpoolWait.

Sincronización interna

Cuando se emite una solicitud de E/S, se asigna una estructura para representar la solicitud. Esta estructura se denomina paquete de solicitud de E/S (IRP). Con la E/S sincrónica, el subproceso compila el IRP, lo envía a la pila de dispositivos y espera en el kernel para que se complete el IRP. Con E/S asincrónica, el subproceso compila el IRP y lo envía a la pila de dispositivos. La pila puede completar el IRP inmediatamente o podría devolver un estado pendiente que indica que la solicitud está en curso. Cuando esto sucede, el IRP sigue asociado al subproceso, por lo que se cancelará si el subproceso finaliza o llama a una función como CancelIo. Mientras tanto, el subproceso puede seguir realizando otras tareas mientras la pila de dispositivos continúa procesando el IRP.

Hay varias maneras en que el sistema puede indicar que el IRP se ha completado:

  • Actualice la estructura superpuesta con el resultado de la operación para que el subproceso pueda sondear para determinar si la operación se ha completado.
  • Indique el evento en la estructura superpuesta para que un subproceso pueda sincronizarse en el evento y reactivarse cuando se complete la operación.
  • Poner en cola el IRP al APC pendiente del subproceso para que el subproceso ejecute la rutina de APC cuando entre en un estado de espera alertable y vuelva de la operación de espera con un estado que indique que ejecutó una o varias rutinas de APC.
  • Poner en cola el IRP a un puerto de finalización de E/S, donde se ejecutará mediante el siguiente subproceso que espera en el puerto de finalización.

Los subprocesos que esperan en un puerto de finalización de E/S no esperan en un estado de alerta. Por lo tanto, si esos subprocesos emiten IRP que se establecen para completarse como APC en el subproceso, esas finalizaciones ipc no se producirán de forma oportuna; solo se producirán si el subproceso recoge una solicitud del puerto de finalización de E/S y, a continuación, entra en una espera que se puede alertar.

Uso de un temporizador de espera con una llamada a procedimiento asincrónico