Partager via


Synchronisation et sortie superposées

Vous pouvez effectuer des opérations d’E/S synchrones ou asynchrones (également appelées chevauchement) sur des fichiers, des canaux nommés et des périphériques de communication série. LesWriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipeet fonctions TransactNamedPipe peuvent être exécutées de manière synchrone ou asynchrone. Les fonctions ReadFileEx et WriteFileEx ne peuvent être effectuées que de manière asynchrone.

Lorsqu’une fonction est exécutée de façon synchrone, elle ne retourne pas tant que l’opération n’est pas terminée. Cela signifie que l’exécution du thread appelant peut être bloquée pendant une période indéfinie pendant qu’elle attend la fin d’une opération fastidieuse. Les fonctions appelées pour une opération superposée peuvent retourner immédiatement, même si l’opération n’a pas été terminée. Cela permet d’exécuter une opération d’E/S fastidieuse en arrière-plan pendant que le thread appelant est libre d’effectuer d’autres tâches. Par exemple, un thread unique peut effectuer des opérations d’E/S simultanées sur différents handles, ou même des opérations de lecture et d’écriture simultanées sur le même handle.

Pour synchroniser son exécution avec l’achèvement de l’opération superposée, le thread appelant utilise la fonction GetOverlappedResult, la fonction GetOverlappedResultEx ou l’une des fonctions d’attente pour déterminer quand l’opération se chevauche a été terminée. Vous pouvez également utiliser la macro HasOverlappedIoCompleted pour interroger l’achèvement.

Pour annuler toutes les opérations d’E/S asynchrones en attente, utilisez la fonction CancelIoEx et fournissez une structure SE CHEVAUCHER qui spécifie la demande d’annulation. Utilisez la fonction CancelIo pour annuler les opérations d’E/S asynchrones en attente émises par le thread appelant pour le handle de fichier spécifié.

Les opérations qui se chevauchent nécessitent un fichier, un canal nommé ou un appareil de communication créé avec l’indicateur de FILE_FLAG_OVERLAPPED. Lorsqu’un thread appelle une fonction (telle que la fonction ReadFile) pour effectuer une opération qui se chevauche, le thread appelant doit spécifier un pointeur vers une structureCHEVAUCHEMENT. (Si ce pointeur est null, la valeur de retour de la fonction peut indiquer incorrectement que l’opération s’est terminée.) Tous les membres de la structure SE CHEVAUCHER doivent être initialisés à zéro, sauf si un événement sera utilisé pour signaler l’achèvement d’une opération d’E/S. Si un événement est utilisé, le membre hEvent de la structure OVERLAPPED spécifie un handle pour l’objet d’événement alloué. Le système définit l’état de l’objet d’événement sur non signé lorsqu’un appel à la fonction d’E/S retourne avant la fin de l’opération. Le système définit l’état de l’objet d’événement à signaler une fois l’opération terminée. Un événement est nécessaire uniquement s’il y aura plusieurs opérations d’E/S en attente en même temps. Si un événement n’est pas utilisé, chaque opération d’E/S terminée signale le fichier, le canal nommé ou l’appareil de communication.

Lorsqu’une fonction est appelée pour effectuer une opération qui se chevauche, l’opération peut être terminée avant le retour de la fonction. Lorsque cela se produit, les résultats sont gérés comme si l’opération avait été effectuée de manière synchrone. Si l’opération n’a pas été terminée, toutefois, la valeur de retour de la fonction est FALSE, et la fonction GetLastError retourne ERROR_IO_PENDING.

Un thread peut gérer les opérations qui se chevauchent par l’une des deux méthodes suivantes :

  • Utilisez la fonction GetOverlappedResult ou GetOverlappedResultEx pour attendre la fin de l’opération qui se chevauche. Si GetOverlappedResultEx est utilisé, le thread appelant peut spécifier un délai d’attente pour l’opération qui se chevauche ou effectuer une attente alertable.
  • Spécifiez un handle pour l’objet d’événement de réinitialisation manuelle de la structurequi se chevauche dans l’une des fonctions d’attente , puis, une fois la fonction d’attente retournée, appelez GetOverlappedResult ou GetOverlappedResultEx. La fonction retourne les résultats de l’opération qui se chevauche et, pour les fonctions dans lesquelles ces informations sont appropriées, elle signale le nombre réel d’octets transférés.

Lors de l’exécution de plusieurs opérations superposées simultanées sur un thread unique, le thread appelant doit spécifier une structure SE CHEVAUCHER pour chaque opération. Chaque structure SUPERPOSÉE doit spécifier un handle à un autre objet d’événement de réinitialisation manuelle. Pour attendre la fin de l’une des opérations qui se chevauchent, le thread spécifie tous les handles d’événements de réinitialisation manuelle en tant que critères d’attente dans l’une des fonctions d’attente d’attente. La valeur de retour de la fonction d’attente à plusieurs objets indique l’objet d’événement de réinitialisation manuelle signalé, afin que le thread puisse déterminer l’opération qui se chevauche a provoqué la fin de l’opération d’attente.

Il est plus sûr d’utiliser un objet d’événement distinct pour chaque opération qui se chevauche, plutôt que de spécifier aucun objet d’événement ou de réutiliser le même objet d’événement pour plusieurs opérations. Si aucun objet d’événement n’est spécifié dans la structureSE CHEVAUCHER, le système signale l’état du fichier, du canal nommé ou de l’appareil de communication lorsque l’opération se chevauche. Par conséquent, vous pouvez spécifier ces handles en tant qu’objets de synchronisation dans une fonction d’attente, même si leur utilisation à cet effet peut être difficile à gérer, car, lors de l’exécution d’opérations simultanées superposées sur le même fichier, un canal nommé ou un appareil de communication, il n’existe aucun moyen de savoir quelle opération a provoqué la signalisation de l’état de l’objet.

Un thread ne doit pas réutiliser un événement avec l’hypothèse que l’événement ne sera signalé que par l’opération superposée de ce thread. Un événement est signalé sur le même thread que l’opération qui se chevauche. L’utilisation du même événement sur plusieurs threads peut entraîner une condition de concurrence dans laquelle l’événement est signalé correctement pour le thread dont l’opération se termine en premier et prématurément pour d’autres threads à l’aide de cet événement. Ensuite, lorsque l’opération qui se chevauche suivante se termine, l’événement est signalé à nouveau pour tous les threads utilisant cet événement, et ainsi de suite jusqu’à ce que toutes les opérations se chevauchent soient terminées.

Pour obtenir des exemples illustrant l’utilisation d’opérations superposées, de routines d’achèvement et de la fonction GetOverlappedResult, consultez Using Pipes.

Windows Vista, Windows Server 2003 et Windows XP :

Veillez à réutiliser structures superposées. Si structures de SUPERPOSÉes sont réutilisées sur plusieurs threads et GetOverlappedResult est appelée avec le paramètre bWait défini sur TRUE, le thread appelant doit s’assurer que l’événement associé est signalé avant de réutiliser la structure. Pour ce faire, utilisez la fonction WaitForSingleObject après avoir appelé GetOverlappedResult pour forcer le thread à attendre la fin de l’opération. Notez que l’objet d’événement doit être un objet d’événement de réinitialisation manuelle. Si un objet d’événement autoreset est utilisé, l’appel de GetOverlappedResult avec le paramètre défini sur TRUE provoque le blocage indéfini de la fonction. Ce comportement a changé à partir de Windows 7 et Windows Server 2008 R2 pour les applications qui spécifient Windows 7 comme système d’exploitation pris en charge dans le manifeste de l’application. Pour plus d’informations, consultez manifestes d’application.

Concepts d’E/S