Compartir a través de


E/S de canalización sincrónica y superpuesta

Las funciones ReadFile, WriteFile, TransactNamedPipe y ConnectNamedPipe pueden realizar operaciones de entrada y salida en una canalización de forma sincrónica o asincrónica. Cuando una función se ejecuta de forma sincrónica, no devuelve hasta que se completa la operación que realiza. Esto significa que la ejecución del subproceso que realiza la llamada se puede bloquear durante un período indefinido mientras espera a que se complete una operación que consume mucho tiempo. Cuando una función se ejecuta de forma asincrónica, se devuelve inmediatamente, incluso si no se ha completado la operación. Esto permite ejecutar una operación que consume mucho tiempo en segundo plano mientras el subproceso que realiza la llamada es libre para realizar otras tareas.

El uso de E/S asincrónica permite que un servidor de canalización use un bucle que realice los pasos siguientes:

  1. Especifique varios objetos de evento en una llamada a la función wait y espere a que uno de los objetos se establezca en el estado señalado.
  2. Use el valor devuelto de la función wait para determinar qué operación superpuesta ha finalizado.
  3. Realice las tareas necesarias para limpiar la operación completada e iniciar la siguiente operación para ese identificador de canalización. Esto puede implicar iniciar otra operación superpuesta para el mismo identificador de canalización.

Las operaciones superpuestas permiten que una canalización lea y escriba datos simultáneamente y que un único subproceso realice operaciones simultáneas de E/S en varios identificadores de canalización. Esto permite que un servidor de canalización de un solo subproceso controle las comunicaciones con varios clientes de canalización de forma eficaz. Para obtener un ejemplo, vea Servidor de canalización con nombre mediante E/S superpuesta.

Para que un servidor de canalización use operaciones sincrónicas para comunicarse con más de un cliente, debe crear un subproceso independiente para cada cliente de canalización para que uno o varios subprocesos se puedan ejecutar mientras otros subprocesos están esperando. Para obtener un ejemplo de un servidor de canalización multiproceso que usa operaciones sincrónicas, consulte Servidor de canalización multiproceso.

Habilitación de la operación asincrónica

Las funciones ReadFile, WriteFile, TransactNamedPipe y ConnectNamedPipe solo se pueden realizar de forma asincrónica si habilita el modo superpuesto para el identificador de canalización especificado y especifica un puntero válido a una estructura SUPERPUESTA . Si el puntero SUPERPUESTO es NULL, el valor devuelto de la función puede indicar incorrectamente que se ha completado la operación. Por lo tanto, se recomienda encarecidamente que si crea un identificador con FILE_FLAG_OVERLAPPED y desea un comportamiento asincrónico, siempre debe especificar una estructura SUPERPUESTA válida.

El miembro hEvent de la estructura SUPERPUESTA especificada debe contener un identificador para un objeto de evento de restablecimiento manual. Se trata de un objeto de sincronización creado por la función CreateEvent . El subproceso que inicia la operación superpuesta usa el objeto de evento para determinar cuándo ha finalizado la operación. No debe usar el identificador de canalización para la sincronización al realizar operaciones simultáneas en el mismo identificador porque no hay ninguna manera de saber qué finalización de la operación provocó que se señalizara el identificador de canalización. La única técnica confiable para realizar operaciones simultáneas en el mismo identificador de canalización es usar una estructura SUPERPUESTA independiente con su propio objeto de evento para cada operación. Para obtener más información sobre los objetos de evento, vea Sincronización.

Además, puede recibir una notificación cuando se complete una operación superpuesta mediante las funciones GetQueuedCompletionStatus o GetQueuedCompletionStatusEx . En este caso, no es necesario asignar el evento de restablecimiento manual en la estructura SUPERPUESTA y la finalización se produce en el identificador de canalización de la misma manera que una operación asincrónica de lectura o escritura. Para obtener más información, consulte Puertos de finalización de E/S.

Cuando las operaciones ReadFile, WriteFile, TransactNamedPipe y ConnectNamedPipe se realizan de forma asincrónica, se produce una de las siguientes acciones:

  • Si la operación se completa cuando se devuelve la función, el valor devuelto indica el éxito o error de la operación. Si se produce un error, el valor devuelto es cero y la función GetLastError devuelve algo distinto de ERROR_IO_PENDING.
  • Si la operación no ha finalizado cuando se devuelve la función, el valor devuelto es cero y GetLastError devuelve ERROR_IO_PENDING. En este caso, el subproceso que llama debe esperar hasta que finalice la operación. A continuación, el subproceso que llama debe llamar a la función GetOverlappedResult para determinar los resultados.

Usar rutinas de finalización

Las funciones ReadFileEx y WriteFileEx proporcionan otra forma de E/S superpuesta. A diferencia de las funciones ReadFile y WriteFile superpuestas, que usan un objeto de evento para indicar la finalización, las funciones extendidas especifican una rutina de finalización. Una rutina de finalización es una función que se pone en cola para su ejecución cuando finaliza la operación de lectura o escritura. La rutina de finalización no se ejecuta hasta que el subproceso que llamó a ReadFileEx y WriteFileEx inicia una operación de espera alertable llamando a una de las funciones de espera que se pueden alertar con el parámetro fAlertable establecido en TRUE. En una operación de espera alertable, las funciones también devuelven cuando se pone en cola una rutina de finalización ReadFileEx o WriteFileEx para su ejecución. Un servidor de canalización puede usar las funciones extendidas para realizar una secuencia de operaciones de lectura y escritura para cada cliente que se conecta a él. Cada operación de lectura o escritura de la secuencia especifica una rutina de finalización y cada rutina de finalización inicia el siguiente paso de la secuencia. Para obtener un ejemplo, vea Servidor de canalización con nombre mediante rutinas de finalización.