E/S de canal synchrone et superposée

Les fonctions ReadFile, WriteFile, TransactNamedPipe et ConnectNamedPipe peuvent effectuer des opérations d’entrée et de sortie sur un canal de manière synchrone ou asynchrone. Lorsqu’une fonction s’exécute de manière synchrone, elle ne retourne pas tant que l’opération qu’elle effectue n’est pas terminée. Cela signifie que l’exécution du thread appelant peut être bloquée pendant une période indéterminée pendant qu’il attend la fin d’une opération fastidieuse. Lorsqu’une fonction s’exécute de manière asynchrone, elle retourne immédiatement, même si l’opération n’est pas terminée. Cela permet d’exécuter une opération fastidieuse en arrière-plan, tandis que le thread appelant est libre d’effectuer d’autres tâches.

L’utilisation d’E/S asynchrones permet à un serveur de canal d’utiliser une boucle qui effectue les étapes suivantes :

  1. Spécifiez plusieurs objets d’événement dans un appel à la fonction wait et attendez que l’un des objets soit défini sur l’état signalé.
  2. Utilisez la valeur de retour de la fonction d’attente pour déterminer l’opération qui se chevauche est terminée.
  3. Effectuez les tâches nécessaires pour propre l’opération terminée et lancer l’opération suivante pour ce handle de canal. Cela peut impliquer le démarrage d’une autre opération qui se chevauche pour le même handle de canal.

Les opérations qui se chevauchent permettent à un canal de lire et d’écrire des données simultanément et à un seul thread d’effectuer des opérations d’E/S simultanées sur plusieurs handles de canal. Cela permet à un serveur de canal monothread de gérer efficacement les communications avec plusieurs clients de canal. Pour obtenir un exemple, consultez Serveur de canal nommé utilisant des E/S superposées.

Pour qu’un serveur canal utilise des opérations synchrones pour communiquer avec plusieurs clients, il doit créer un thread distinct pour chaque client de canal afin qu’un ou plusieurs threads puissent s’exécuter pendant que d’autres threads sont en attente. Pour obtenir un exemple de serveur de canal multithread qui utilise des opérations synchrones, consultez Serveur de canal multithread.

Activation de l’opération asynchrone

Les fonctions ReadFile, WriteFile, TransactNamedPipe et ConnectNamedPipe ne peuvent être exécutées de manière asynchrone que si vous activez le mode superposé pour le handle de canal spécifié et si vous spécifiez un pointeur valide vers une structure CHEVAUCHEMENT . Si le pointeur CHEVAUCHEMENT ESTNULL, la valeur de retour de la fonction peut indiquer à tort que l’opération a été effectuée. Par conséquent, si vous créez un handle avec FILE_FLAG_OVERLAPPED et que vous souhaitez un comportement asynchrone, nous vous recommandons de toujours spécifier une structure CHEVAUCHÉE valide.

Le membre hEvent de la structure OVERLAPPED spécifiée doit contenir un handle pour un objet d’événement de réinitialisation manuelle. Il s’agit d’un objet de synchronisation créé par la fonction CreateEvent . Le thread qui lance l’opération qui se chevauche utilise l’objet event pour déterminer quand l’opération est terminée. Vous ne devez pas utiliser le handle de canal pour la synchronisation lors de l’exécution d’opérations simultanées sur le même handle, car il n’existe aucun moyen de savoir quelle opération est terminée à l’origine du signal du handle de canal. La seule technique fiable pour effectuer des opérations simultanées sur le même handle de canal consiste à utiliser une structure CHEVAUCHEMENT DISTINCTE avec son propre objet d’événement pour chaque opération. Pour plus d’informations sur les objets d’événement, consultez Synchronisation.

En outre, vous pouvez être averti lorsqu’une opération qui se chevauche se termine à l’aide des fonctions GetQueuedCompletionStatus ou GetQueuedCompletionStatusEx . Dans ce cas, vous n’avez pas besoin d’affecter l’événement de réinitialisation manuelle dans la structure OVERLAPPED , et l’achèvement se produit sur le handle de canal de la même façon qu’une opération de lecture ou d’écriture asynchrone. Pour plus d’informations, consultez Ports d’achèvement des E/S.

Lorsque les opérations ReadFile, WriteFile, TransactNamedPipe et ConnectNamedPipe sont effectuées de manière asynchrone, l’une des opérations suivantes se produit :

  • Si l’opération est terminée lorsque la fonction est retournée, la valeur de retour indique la réussite ou l’échec de l’opération. Si une erreur se produit, la valeur de retour est égale à zéro et la fonction GetLastError retourne autre chose que ERROR_IO_PENDING.
  • Si l’opération n’est pas terminée lorsque la fonction est retournée, la valeur de retour est égale à zéro et GetLastError renvoie ERROR_IO_PENDING. Dans ce cas, le thread appelant doit attendre que l’opération soit terminée. Le thread appelant doit ensuite appeler la fonction GetOverlappedResult pour déterminer les résultats.

Utilisation de routines d’achèvement

Les fonctions ReadFileEx et WriteFileEx fournissent une autre forme d’E/S superposées. Contrairement aux fonctions ReadFile et WriteFile qui se chevauchent, qui utilisent un objet d’événement pour signaler l’achèvement, les fonctions étendues spécifient une routine d’achèvement. Une routine d’achèvement est une fonction qui est mise en file d’attente pour l’exécution lorsque l’opération de lecture ou d’écriture est terminée. La routine d’achèvement n’est pas exécutée tant que le thread qui a appelé ReadFileEx et WriteFileEx démarre une opération d’attente pouvant être alertée en appelant l’une des fonctions d’attente pouvant être alertée avec le paramètre fAlertable défini sur TRUE. Dans une opération d’attente pouvant être alertée, les fonctions retournent également lorsqu’une routine d’achèvement ReadFileEx ou WriteFileEx est mise en file d’attente pour l’exécution. Un serveur canal peut utiliser les fonctions étendues pour effectuer une séquence d’opérations de lecture et d’écriture pour chaque client qui s’y connecte. Chaque opération de lecture ou d’écriture dans la séquence spécifie une routine d’achèvement, et chaque routine d’achèvement lance l’étape suivante de la séquence. Pour obtenir un exemple, consultez Serveur de canal nommé à l’aide de routines d’achèvement.