Partager via


Contextes

Ce document décrit le rôle des contextes pendant le runtime d'accès concurrentiel. Un thread joint à un planificateur porte le nom de contexte d'exécution, ou simplement de contexte. La fonction Concurrency::wait et la classe Concurrency::Context vous permettent de contrôler le comportement des contextes. Utilisez la fonction wait pour interrompre le contexte actuel pendant une durée spécifiée. Utilisez la classe Context lorsque vous avez besoin d'exercer un contrôle plus important lorsque les contextes se bloquent, se débloquent et cèdent, ou lorsque vous souhaitez à surabonner le contexte actuel.

Conseil

Le runtime d'accès concurrentiel fournit un planificateur par défaut. Par conséquent, vous n'êtes pas tenu d'en créer un dans votre application. Étant donné que le planificateur de tâches vous aide à affiner les performances de vos applications, nous vous recommandons de commencer avec la Bibliothèque de modèles parallèles ou la Bibliothèque d'agents asynchrones si vous ne connaissez pas encore le runtime d'accès concurrentiel.

Fonction wait

La fonction Concurrency::wait cède de façon coopérative l'exécution du contexte actuel pendant un nombre de millisecondes déterminé. Le runtime utilise la durée de cession pour effectuer d'autres tâches. Une fois le délai écoulé, le runtime replanifie le contexte pour l'exécution. Par conséquent, la fonction wait peut interrompre le contexte actuel pendant plus longtemps que la valeur prévue par le paramètre milliseconds.

Le passage de la valeur 0 (zéro) pour le paramètre milliseconds fait en sorte que le runtime interrompe le contexte actuel jusqu'à ce que tous les autres contextes actifs aient l'opportunité d'exécuter le travail. Cela vous permet de céder une tâche à toutes les autres tâches actives.

Exemple

Pour obtenir un exemple qui utilise la fonction wait pour céder le contexte actuel, et donc permettre à d'autres contextes de s'exécuter, consultez Comment : utiliser des groupes de planifications pour influencer l'ordre d'exécution.

Classe Context

La classe Concurrency::Context fournit une abstraction de programmation pour un contexte d'exécution. Elle fournit deux fonctionnalités importantes : la capacité à bloquer, débloquer et céder le contexte actuel de manière coopérative, et la capacité à surabonner le contexte actuel

Blocage coopératif

La classe Context vous permet de bloquer ou de céder le contexte d'exécution actuel. Le blocage ou la cession est utile lorsque le contexte actuel ne peut pas continuer car une ressource n'est pas disponible.

La méthode Concurrency::Context::Block bloque le contexte actuel. Un contexte bloqué cède ses ressources de traitement afin que le runtime puisse effectuer d'autres tâches. La méthode Concurrency::Context::Unblock débloque un contexte bloqué. La méthode Context::Unblock doit être appelée à partir d'un contexte différent de celui qui a appelé Context::Block. Le runtime lève Concurrency::context_self_unblock si un contexte tente de se débloquer.

Pour bloquer et débloquer un contexte de manière coopérative, il faut généralement appeler Concurrency::Context::CurrentContext pour extraire un pointeur vers l'objet Context qui est associé au thread actuel, puis enregistrer le résultat. Il faut ensuite appeler la méthode Context::Block pour bloquer le contexte actuel. Puis, il faut appeler Context::Unblock à partir d'un contexte distinct pour débloquer le contexte bloqué.

Vous devez faire correspondre chaque paire d'appels à Context::Block et Context::Unblock. Le runtime lève Concurrency::context_unblock_unbalanced lorsque la méthode Context::Block ou Context::Unblock est appelée consécutivement sans un appel correspondant à l'autre méthode. Toutefois, vous n'êtes pas obligé d'appeler Context::Block avant d'appeler Context::Unblock. Par exemple, si un contexte appelle Context::Unblock avant qu'un autre contexte n'appelle Context::Block pour le même contexte, ce contexte reste non bloqué.

La méthode Concurrency::Context::Yield cède l'exécution afin que le runtime puisse effectuer d'autres tâches, puis replanifier le contexte pour l'exécution. Lorsque vous appelez la méthode Context::Block, le runtime ne replanifie pas le contexte.

Exemple

Pour obtenir un exemple qui utilise les méthodes Context::Block, Context::Unblock et Context::Yield pour implémenter une classe de sémaphore coopérative, consultez Comment : utiliser la classe Context pour implémenter un sémaphore coopératif.

Surabonnement

Le planificateur par défaut crée un nombre de threads égal au nombre de threads matériels disponibles. Vous pouvez utiliser le surabonnement pour créer des threads supplémentaires pour un thread matériel donné.

Pour les opérations nécessitant de nombreuses ressources de calcul, le surabonnement ne monte généralement pas en charge car il introduit une charge supplémentaire. Toutefois, dans le cas de tâches présentant une forte latence, par exemple la lecture de données à partir d'un disque ou d'une connexion réseau, le surabonnement peut améliorer l'efficacité globale de certaines applications.

Notes

Activez uniquement le surabonnement des threads non UMS, créés par le runtime d'accès concurrentiel. Le surabonnement n'a aucun effet lorsqu'il est appelé par un thread n'ayant pas été créé par le runtime (y compris le thread principal). De plus, le surabonnement n'a aucun effet lorsqu'il est appelé par un contexte qui utilise des threads UMS pour planifier des tâches, car ils permettent au planificateur d'utiliser pleinement les ressources dans le cas d'opérations bloquantes.

Pour activer le surabonnement dans le contexte actuel, appelez la méthode Concurrency::Context::Oversubscribe en ayant défini le paramètre _BeginOversubscription avec la valeur true. Lorsque vous activez le surabonnement sur un thread qui a été créé par le runtime d'accès concurrentiel, le runtime crée un thread supplémentaire. Une fois que toutes les tâches qui requièrent le surabonnement sont terminées, appelez Context::Oversubscribe avec le paramètre _BeginOversubscription défini à la valeur false.

Vous pouvez activer le surabonnement plusieurs fois à partir du contexte actuel, mais vous devez le désactiver le même nombre de fois. Le surabonnement peut également être imbriqué ; autrement dit, une tâche créée par une autre tâche qui utilise le surabonnement peut également surabonner son contexte. Toutefois, si une tâche imbriquée et son parent appartiennent au même contexte, seul l'appel le plus à l'extérieur à Context::Oversubscribe provoque la création d'un thread supplémentaire.

Notes

Le runtime lève Concurrency::invalid_oversubscribe_operation si le surabonnement est désactivé avant d'être activé.

Exemple

Pour obtenir un exemple qui utilise le surabonnement pour compenser la latence provoquée par la lecture de données à partir d'une connexion réseau, consultez Comment : utiliser le surabonnement pour compenser la latence.

Voir aussi

Tâches

Comment : utiliser le surabonnement pour compenser la latence

Concepts

Planificateur de tâches (runtime d'accès concurrentiel)

Autres ressources

Comment : utiliser des groupes de planifications pour influencer l'ordre d'exécution

Comment : utiliser la classe Context pour implémenter un sémaphore coopératif

Historique des modifications

Date

Historique

Motif

Juillet 2010

Réorganisation du contenu.

Améliorations apportées aux informations.