Fonctions d’attente

Les fonctions d’attente permettent à un thread de bloquer sa propre exécution. Les fonctions d’attente ne retournent pas tant que les critères spécifiés n’ont pas été remplis. Le type de fonction d’attente détermine l’ensemble de critères utilisés. Lorsqu’une fonction d’attente est appelée, elle vérifie si les critères d’attente ont été remplis. Si les critères n’ont pas été remplis, le thread appelant passe à l’état d’attente jusqu’à ce que les conditions des critères d’attente soient remplies ou que l’intervalle de délai d’attente spécifié s’écoule.

Fonctions d’attente à objet unique

Les fonctions SignalObjectAndWait, WaitForSingleObject et WaitForSingleObjectEx nécessitent un handle pour un objet de synchronisation. Ces fonctions retournent lorsque l’une des opérations suivantes se produit :

  • L’objet spécifié est à l’état signalé.
  • L’intervalle de délai d’attente s’écoule. L’intervalle de délai d’attente peut être défini sur INFINITE pour spécifier que l’attente n’expire pas.

La fonction SignalObjectAndWait permet au thread appelant de définir atomiquement l’état d’un objet sur signalé et d’attendre que l’état d’un autre objet soit défini sur signalé.

Fonctions d’attente à plusieurs objets

Les fonctions WaitForMultipleObjects, WaitForMultipleObjectsEx, MsgWaitForMultipleObjects et MsgWaitForMultipleObjectsEx permettent au thread appelant de spécifier un tableau contenant un ou plusieurs handles d’objet de synchronisation. Ces fonctions retournent lorsque l’une des opérations suivantes se produit :

  • L’état de l’un des objets spécifiés est signalé ou les états de tous les objets ont été définis sur signalés. Vous contrôlez si un ou tous les états seront utilisés dans l’appel de fonction.
  • L’intervalle de délai d’attente s’écoule. L’intervalle de délai d’attente peut être défini sur INFINITE pour spécifier que l’attente n’expire pas.

Les fonctions MsgWaitForMultipleObjects et MsgWaitForMultipleObjectsEx vous permettent de spécifier des objets d’événement d’entrée dans le tableau de handles d’objets. Cette opération est effectuée lorsque vous spécifiez le type d’entrée à attendre dans la file d’attente d’entrée du thread. Par exemple, un thread peut utiliser MsgWaitForMultipleObjects pour bloquer son exécution jusqu’à ce que l’état d’un objet spécifié ait été signalé et qu’une entrée de souris soit disponible dans la file d’attente d’entrée du thread. Le thread peut utiliser la fonction GetMessage , PeekMessageA ou PeekMessageW pour récupérer l’entrée.

En attendant que les états de tous les objets soient signalés, ces fonctions à plusieurs objets ne modifient pas les états des objets spécifiés tant que les états de tous les objets n’ont pas été définis. Par exemple, l’état d’un objet mutex peut être signalé, mais le thread appelant n’obtient pas la propriété tant que les états des autres objets spécifiés dans le tableau n’ont pas également été définis sur signalés. En attendant, un autre thread peut obtenir la propriété de l’objet mutex, ce qui lui permet de définir son état sur non signé.

En attendant que l’état d’un objet unique soit défini sur signalé, ces fonctions à plusieurs objets case activée les handles dans le tableau dans l’ordre commençant par l’index 0, jusqu’à ce que l’un des objets soit signalé. Si plusieurs objets sont signalés, la fonction retourne l’index du premier handle dans le tableau dont l’objet a été signalé.

Fonctions d’attente pouvant être alertables

Les fonctions MsgWaitForMultipleObjectsEx, SignalObjectAndWait, WaitForMultipleObjectsEx et WaitForSingleObjectEx diffèrent des autres fonctions d’attente en ce qu’elles peuvent éventuellement effectuer une opération d’attente pouvant être alertable. Dans une opération d’attente pouvant être alertée, la fonction peut retourner lorsque les conditions spécifiées sont remplies, mais elle peut également retourner si le système met en file d’attente une routine d’achèvement des E/S ou un APC pour exécution par le thread en attente. Pour plus d’informations sur les opérations d’attente pouvant être alertées et les routines d’achèvement des E/S, consultez Synchronisation et entrée et sortie superposées. Pour plus d’informations sur les API, consultez Appels de procédure asynchrone.

Fonctions d’attente inscrites

La fonction RegisterWaitForSingleObject diffère des autres fonctions d’attente en ce que l’opération d’attente est effectuée par un thread du pool de threads. Lorsque les conditions spécifiées sont remplies, la fonction de rappel est exécutée par un thread de travail à partir du pool de threads.

Par défaut, une opération d’attente inscrite est une opération d’attente multiple. Le système réinitialise le minuteur chaque fois que l’événement est signalé (ou que l’intervalle de délai d’attente s’écoule) jusqu’à ce que vous appeliez la fonction UnregisterWaitEx pour annuler l’opération. Pour spécifier qu’une opération d’attente ne doit être exécutée qu’une seule fois, définissez le paramètre dwFlags de RegisterWaitForSingleObjectsur WT_EXECUTEONLYONCE.

Si le thread appelle des fonctions qui utilisent des API, définissez le paramètre dwFlags de RegisterWaitForSingleObjectsur WT_EXECUTEINPERSISTENTTHREAD.

Attente sur une adresse

Un thread peut utiliser la fonction WaitOnAddress pour attendre que la valeur d’une adresse cible passe d’une valeur non souhaitée à une autre valeur. Cela permet aux threads d’attendre qu’une valeur change sans avoir à tourner ou à gérer les problèmes de synchronisation qui peuvent survenir lorsque le thread capture une valeur non souhaitée, mais que la valeur change avant que le thread puisse attendre.

WaitOnAddress retourne quand le code qui modifie la valeur cible signale la modification en appelant WakeByAddressSingle pour réveiller un thread d’attente unique ou WakeByAddressAll pour réveiller tous les threads en attente. Si un intervalle de délai d’attente est spécifié avec WaitOnAddress et qu’aucun thread n’appelle une fonction de veille, la fonction retourne lorsque l’intervalle de délai d’attente s’écoule. Si aucun intervalle de délai d’attente n’est spécifié, le thread attend indéfiniment.

Fonctions d’attente et intervalles de délai d’attente

La précision de l’intervalle de délai d’attente spécifié dépend de la résolution de l’horloge système. L’horloge système « tourne » à un rythme constant. Si l’intervalle de délai d’attente est inférieur à la résolution de l’horloge système, le délai d’attente peut être inférieur à la durée spécifiée. Si l’intervalle de délai d’attente est supérieur à une graduation, mais inférieur à deux, l’attente peut être comprise entre une et deux cycles, et ainsi de suite.

Pour augmenter la précision de l’intervalle de délai d’attente pour les fonctions d’attente, appelez la fonction timeGetDevCaps pour déterminer la résolution minimale du minuteur prise en charge et la fonction timeBeginPeriod pour définir la résolution du minuteur à son minimum. Soyez prudent lorsque vous appelez timeBeginPeriod, car les appels fréquents peuvent affecter considérablement l’horloge système, l’utilisation de l’alimentation du système et le planificateur. Si vous appelez timeBeginPeriod, appelez-la une fois plus tôt dans l’application et veillez à appeler la fonction timeEndPeriod à la toute fin de l’application.

Fonctions d’attente et objets de synchronisation

Les fonctions d’attente peuvent modifier les états de certains types d’objets de synchronisation. La modification se produit uniquement pour l’objet ou les objets dont l’état signalé a provoqué le retour de la fonction. Les fonctions d’attente peuvent modifier les états des objets de synchronisation comme suit :

  • Le nombre d’un objet sémaphore diminue d’un, et l’état du sémaphore est défini sur non signé si son nombre est égal à zéro.
  • Les états des objets mutex, d’événement de réinitialisation automatique et de notification de modification sont définis sur non signés.
  • L’état d’un minuteur de synchronisation est défini sur non signé.
  • Les états de l’événement de réinitialisation manuelle, du minuteur de réinitialisation manuelle, du processus, du thread et des objets d’entrée de console ne sont pas affectés par une fonction d’attente.

Fonctions d’attente et création de Windows

Vous devez être prudent lorsque vous utilisez les fonctions d’attente et le code qui créent directement ou indirectement des fenêtres. Si un thread crée des fenêtres, il doit traiter les messages. Les diffusions de messages sont envoyées à toutes les fenêtres du système. Si vous avez un thread qui utilise une fonction d’attente sans intervalle de délai d’attente, le système se bloquera. Deux exemples de code qui créent indirectement des fenêtres sont DDE et la fonction CoInitialize . Par conséquent, si vous avez un thread qui crée des fenêtres, utilisez MsgWaitForMultipleObjects ou MsgWaitForMultipleObjectsEx, plutôt que les autres fonctions d’attente.