Synchronisation et chevauchement des entrées et sorties

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

Lorsqu’une fonction est exécutée de manière 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, en attendant la fin d’une opération chronophage. Les fonctions appelées pour l’opération qui se chevauchent 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 chronophage en arrière-plan, alors 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 qui se chevauche, le thread appelant utilise la fonction GetOverlappedResult , la fonction GetOverlappedResultEx ou l’une des fonctions d’attente pour déterminer quand l’opération qui se chevauche est 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 OVERLAPPED 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 périphérique de communication créé avec l’indicateur 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 structure CHEVAUCHEMENT . (Si ce pointeur a la valeur NULL, la valeur de retour de la fonction peut indiquer à tort que l’opération s’est terminée.) Tous les membres de la structure OVERLAPPED doivent être initialisés à zéro, sauf si un événement est 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 à 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/S est retourné avant la fin de l’opération. Le système définit l’état de l’objet d’événement pour qu’il soit signalé lorsque l’opération est terminée. Un événement n’est nécessaire que s’il y a plusieurs opérations d’E/S en cours en même temps. Si aucun événement n’est utilisé, chaque opération d’E/S terminée signale le fichier, le canal nommé ou le périphérique 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. Dans ce cas, 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é effectué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 à l’aide de l’une des deux méthodes suivantes :

  • Utilisez la fonction GetOverlappedResult ou GetOverlappedResultEx pour attendre que l’opération qui se chevauche soit terminée. 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 pouvant être alertée.
  • Spécifiez un handle à l’objet d’événement de réinitialisation manuelle de la structure OVERLAPPED dans l’une des fonctions d’attente , puis, une fois la fonction d’attente retournée, appelez GetOverlappedResult ouGetOverlappedResultEx. La fonction retourne les résultats de l’opération qui s’est chevauchée, et pour les fonctions pour lesquelles ces informations sont appropriées, elle indique le nombre réel d’octets qui ont été transférés.

Lors de l’exécution de plusieurs opérations simultanées qui se chevauchent sur un seul thread, le thread appelant doit spécifier une structure CHEVAUCHEMENT POUR chaque opération. Chaque structure CHEVAUCHEMENT DOIT spécifier un handle pour 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énement de réinitialisation manuelle comme critères d’attente dans l’une des fonctions d’attente à objets multiples. La valeur de retour de la fonction d’attente à plusieurs objets indique quel objet d’événement de réinitialisation manuelle a été signalé, de sorte que le thread peut déterminer quelle opération se chevauche à l’origine 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 ne 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 structure CHEVAUCHEMENT, le système signale l’état du fichier, du canal nommé ou du périphérique de communication lorsque l’opération qui se chevauche est terminée. Ainsi, 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 qui se chevauchent sur le même fichier, le même canal nommé ou le même appareil de communication, il n’existe aucun moyen de savoir quelle opération a provoqué le signal de l’état de l’objet.

Un thread ne doit pas réutiliser un événement en supposant que l’événement sera signalé uniquement par l’opération qui se chevauche. Un événement est signalé sur le même thread que l’opération qui se chevauche qui se termine. L’utilisation du même événement sur plusieurs threads peut entraîner une condition de course 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 utilisant cet événement. Ensuite, lorsque l’opération qui se chevauche suivante se termine, l’événement est à nouveau signalé pour tous les threads utilisant cet événement, et ainsi de suite jusqu’à ce que toutes les opérations qui se chevauchent soient terminées.

Pour obtenir des exemples illustrant l’utilisation d’opérations qui se chevauchent, de routines d’achèvement et de la fonction GetOverlappedResult , consultez Utilisation de canaux.

Windows Vista, Windows Server 2003 et Windows XP :

Soyez prudent lors de la réutilisation des structures CHEVAUCHÉES . Si les structures CHEVAUCHEMENT SONT réutilisées sur plusieurs threads et que GetOverlappedResult est appelé 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 événement autoreset est utilisé, l’appel de GetOverlappedResult avec le paramètre bWait défini sur TRUE entraîne 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