Skip to main content
Cette rubrique présente les objectifs de conception établis lors de la création du nouveau modèle de programmation asynchrone pour le Microsoft Game Development Kit (GDK). Elle présente également les améliorations apportées par rapport au modèle du XBOX One Software Development Kit, en réponse aux commentaires des développeurs.

Dans cette rubrique

Introduction

Le Microsoft Game Development Kit (GDK) a introduit un nouveau modèle de programmation asynchrone conçu pour vous offrir un comportement d’exécution hautement personnalisable et contrôlable, avec une faible surcharge de traitement et de mémoire. Tous les appels d’API asynchrones du Microsoft Game Development Kit (GDK) utilisent ce modèle afin d’assurer la cohérence. Toutefois, les bibliothèques asynchrones peuvent être utilisées directement dans vos propres systèmes de tâches et asynchrones pour gérer la mise en file d’attente et la distribution des tâches. Tirant des leçons du modèle asynchrone précédent du XBOX One Software Development Kit et des commentaires des développeurs, la nouvelle solution du Microsoft Game Development Kit (GDK) vous donne un contrôle complet sur la façon et l’endroit où les tâches asynchrones sont exécutées. Vous pouvez utiliser n’importe quelle conception de threads, qu’il s’agisse d’exécutions synchrones sur un seul thread ou d’exécutions parallèles sur des threads du titre ayant des priorités et des masques d’affinité très précis. Le XBOX One Software Development Kit utilisait uniquement le pool de threads du système. Le changement de paradigme du Microsoft Game Development Kit (GDK) améliore ce qu’était la solution du XBOX One Software Development Kit en utilisant des API C plates de style Win32 ou des API C++ simples. Vous pouvez ainsi gérer directement le moment de l’allocation et de la libération de la mémoire. Les performances peuvent être inspectées plus facilement, et la plupart des appels d’API (ainsi que tous les appels d’API des bibliothèques asynchrones utilisés pour l’exécution des tâches) s’accompagnent d’une garantie de hautes performances.

Objectifs de conception

Les bibliothèques asynchrones sont conçues autour de quelques objectifs clés pour garantir que les titres puissent obtenir les meilleures performances avec une surcharge minimale de l’API ou du système. La liste suivante contient quelques objectifs de haut niveau.
  • Le code asynchrone est cohérent et facile à comprendre et à identifier.
  • Vous êtes libre de gérer entièrement le comportement d’exécution des rappels.
  • Vous pouvez utiliser les threads comme vous le souhaitez.
  • Les performances et l’utilisation de la mémoire sont cohérentes et faciles à gérer.
  • La surcharge du système pour l’exécution des tâches est faible et utilisable sur les threads principaux.
  • Les bibliothèques asynchrones ne devraient pas être réservées uniquement à l’utilisation des API du Microsoft Game Development Kit (GDK).
Certains de ces objectifs sont abordés dans les sous-sections suivantes et d’autres sont abordés dans la section Améliorations par rapport au XBOX One Software Development Kit de cette rubrique.

Cohérent et multiplateforme

La cohérence établit certaines des attentes suivantes quant à la façon dont les API asynchrones sont écrites et se comportent.
  • Les méthodes et les données sont préfixées par X, suivi d’un nom de bibliothèque.
  • Les erreurs normales sont signalées au moyen de codes d’erreur HRESULT.
  • Tous les appels asynchrones du Microsoft Game Development Kit (GDK) utilisent un XAsyncBlock.
  • Les méthodes de démarrage asynchrones du Microsoft Game Development Kit (GDK) ont le suffixe Async.
  • Les méthodes de résultat asynchrones du Microsoft Game Development Kit (GDK) ont le suffixe Result.
Être multiplateforme signifie que les mêmes appels d’API asynchrones peuvent être utilisés sur toutes les plateformes ciblées par le Microsoft Game Development Kit (GDK). Ces plateformes comprennent actuellement les PC Windows (rubrique sous NDA), les consoles de la famille XBOX One et les consoles XBOX Series (rubrique sous NDA). Que vous utilisiez les bibliothèques asynchrones pour des appels d’API du Microsoft Game Development Kit (GDK) ou pour vos propres fonctionnalités, le processus est toujours le même pour configurer un XAsyncBlock et démarrer la méthode asynchrone. Chaque fois qu’une méthode asynchrone est fournie par une bibliothèque, ces méthodes utilisent les bibliothèques asynchrones pour leur implémentation. Le tableau suivant présente quelques bibliothèques qui exposent des méthodes asynchrones.

Contrôle complet par le développeur

Un aspect important des nouvelles bibliothèques asynchrones est que vous disposez d’un contrôle complet pour permettre la meilleure utilisation possible pour le titre. Cela signifie que de nombreuses parties du modèle sont personnalisables, notamment les suivantes. Lorsqu’une file d’attente de tâches est créée, vous pouvez personnaliser la façon dont les rappels des deux ports sont distribués, comme le montre le tableau suivant. Vous pouvez remplacer la file d’attente de tâches par défaut utilisée par le titre lorsqu’aucune file d’attente de tâches n’est spécifiée à l’aide de XTaskQueueSetCurrentProcessTaskQueue. Si vous voulez vous assurer qu’une file d’attente de tâches est toujours spécifiée, vous pouvez également utiliser cette fonction avec nullptr pour supprimer la file d’attente par défaut. Dans ce cas, une erreur est générée si aucune file d’attente de tâches n’est spécifiée. Si vous préférez utiliser l’interrogation pour les appels asynchrones afin de savoir quand la tâche se termine, vous pouvez utiliser XAsyncGetStatus pour vérifier les codes de retour.

Toute situation de threads

Lorsqu’un port de file d’attente de tâches est configuré pour utiliser la distribution manuelle, il n’y a aucune restriction quant au moment ou à la façon dont le port est distribué. Les bibliothèques asynchrones sont thread-safe dans leur implémentation, de sorte que des comportements personnalisés de threads et de simultanéité peuvent se produire sans verrous. Les sections critiques, les opérations verrouillées (interlocked) et les autres constructions multithread connexes ne sont nécessaires que pour protéger les données utilisateur utilisées dans les rappels, et non les systèmes asynchrones. Lorsque vous utilisez vos propres threads, vous êtes libre de définir les masques d’affinité et les priorités des threads selon les besoins de votre implémentation. Vous pouvez également utiliser la boucle de messages Windows pour gérer la distribution. Le comportement d’exécution des rappels de tâches dans les ports manuels dépend entièrement de la façon dont vos threads sont configurés pour appeler XTaskQueueDispatch, comme le montrent la figure 1 et la figure 2. Figure 1. Comportement d’exécution des rappels avec un seul thread Capture d'écran du comportement d'exécution des rappels avec un seul thread Figure 2. Comportement d’exécution des rappels avec plusieurs threads Capture d'écran du comportement d'exécution des rappels avec plusieurs threads

Améliorations par rapport au XBOX One Software Development Kit

Répondre à vos commentaires et améliorer les solutions antérieures est très important pour le Microsoft Game Development Kit (GDK) (rubrique sous NDA). Les sous-sections suivantes présentent quelques améliorations clés apportées par rapport à la programmation asynchrone dans le XBOX One Software Development Kit.

Fini C++/CLI (WinRT)

Le XBOX One Software Development Kit exigeait l’utilisation de C++/CLI (WinRT) pour le comportement des fonctions asynchrones. Ainsi, le système gérait ses appels aux XBOX services et à d’autres services sans rencontrer de problèmes tels que des fuites de ressources et des erreurs. Toutefois, cela exigeait aussi d’apprendre une nouvelle syntaxe de codage et de tenir compte du découpage implicite du temps et de l’utilisation des ressources par le système. Le modèle asynchrone du Microsoft Game Development Kit (GDK) fait passer le paradigme à un modèle d’API de style C Win32 pour les bibliothèques asynchrones. Le code du Microsoft Game Development Kit (GDK) peut être utilisé directement dans des projets C/C++ sans intégrer l’écosystème WinRT managé. Par conséquent, toutes les allocations et tous les comportements sont isolés et bien compris, avec un comportement en arrière-plan minimal sur les threads du système.

Contrôle complet du comportement des threads

Le XBOX One Software Development Kit offrait une seule façon de gérer les appels asynchrones, soit de les exécuter simultanément sur les threads du pool du système. L’étendue du contrôle se limitait à l’ajustement du pool de threads du système. Dans le Microsoft Game Development Kit (GDK), les threads peuvent utiliser le pool de threads du système comme dans le XBOX One Software Development Kit, ou être personnalisés avec des threads manuels afin de créer le comportement voulu pour l’application. Avec des threads manuels, le comportement d’exécution des rappels est déterminé par la façon et le moment où XTaskQueueDispatch est appelée. Si cette fonction n’est appelée que sur un seul thread, le comportement devient synchrone sur ce thread. Si plusieurs threads appellent simultanément la fonction, chaque appel obtient un rappel différent de la file d’attente de tâches et les exécute en parallèle. Les différents comportements d’exécution des rappels ont été expliqués dans la section Contrôle complet par le développeur de cette rubrique.

Codes d’erreur au lieu d’exceptions

Le Microsoft Game Development Kit (GDK) englobe de nombreuses technologies, anciennes et nouvelles. Par conséquent, la gestion des erreurs peut différer d’une bibliothèque à l’autre. Les bibliothèques asynchrones sont conçues pour être « sans exception ». Cela signifie que les exceptions ne sont pas utilisées pour les erreurs d’appel, le contrôle de flux, le signalement d’état ni aucune autre fin d’exécution. Vous pouvez utiliser votre propre gestion des exceptions dans votre titre. La plupart des erreurs et des codes d’état sont maintenant signalés au moyen de codes HRESULT selon le style de codage Win32 standard. Lorsque le code d’état du résultat n’est pas important, une valeur booléenne peut être utilisée. Lorsqu’une méthode d’API est susceptible de générer des erreurs courantes, ces erreurs sont répertoriées dans la documentation avec une explication de leurs causes. Comme des codes HRESULT sont utilisés, un modèle simple pour vérifier les codes consiste à utiliser les macros Windows SUCCESS() et FAILED(). Pour rechercher des codes d’erreur précis afin de déterminer comment procéder, vous pouvez vérifier la valeur HRESULT. Pour plus d’informations sur la gestion des erreurs dans le Microsoft Game Development Kit (GDK), consultez Gestion des erreurs dans le Microsoft Game Development Kit.

Aucun nettoyage de la mémoire (garbage collection)

Comme le Microsoft Game Development Kit (GDK) ne prend pas en charge C++/CLI (WinRT), cela signifie également qu’aucun nettoyage de la mémoire ne se produit en arrière-plan pendant l’exécution. Toutes les allocations suivies du système d’exploitation sont représentées par des objets HANDLE directs ou par des typedefs de handles personnalisés fournis par les bibliothèques. Vous pouvez faire en sorte que le moment, le comportement et les performances des allocations et des libérations soient gérés par l’appelant à l’aide de handles. Ces allocations et libérations peuvent être déplacées vers des threads de chargement auxiliaires afin d’éviter les accrocs de performances. La libération ne se produit pas de façon inattendue lorsque les performances sont primordiales. Toutefois, le suivi des ressources et la prévention des fuites de mémoire deviennent votre responsabilité. Assurez-vous que tout handle alloué est libéré lorsqu’il n’est plus nécessaire.

Hautes performances garanties

Le modèle asynchrone du XBOX One Software Development Kit, avec son utilisation du framework COM managé, se prêtait à des ratés inattendus de mémoire et de performances qui étaient parfois difficiles à prévoir. Le modèle du Microsoft Game Development Kit (GDK), en revanche, garantit des performances et une empreinte mémoire cohérentes. Comme les threads peuvent être contrôlés, les performances des appels système s’inspectent plus facilement à l’aide d’un profileur ou de code personnalisé. L’exemple de programmation asynchrone de l’ATG comprend des tests intégrés pour mesurer une partie du temps consacré. Le graphique de la figure 3 mesure le temps consacré à la gestion d’une tâche asynchrone avec un fournisseur asynchrone personnalisé. Les threads personnalisés utilisés pour le test exécutent les rappels aussi rapidement que possible. Figure 3. Graphique mesurant la surcharge du système asynchrone Capture d'écran du graphique mesurant la surcharge du système asynchrone La surcharge du système est très faible. Les coûts de surcharge surviennent principalement pendant l’attente que des threads distribuent les ports de la file d’attente de tâches. Le temps global d’une tâche asynchrone, sans tenir compte des coûts de surcharge, correspond au travail réel effectué dans les rappels de la tâche.

Threads sensibles au temps

Les threads sensibles au temps sont une nouvelle spécification que le Microsoft Game Development Kit (GDK) utilise pour identifier les threads du titre qui ne veulent aucune opération bloquante ou d’une durée inattendue. Un utilisateur peut marquer un thread du titre comme sensible au temps en appelant XThreadSetTimeSensitive. Lorsqu’un thread est marqué comme sensible au temps, tout appel d’une méthode d’API du Microsoft Game Development Kit (GDK) sur ce thread qui n’offre pas de performances d’exécution cohérentes et fiables (c’est-à-dire qui n’est pas « sécuritaire pour les threads sensibles au temps ») déclenche une assertion de débogage. Ces méthodes sécuritaires pour les threads sensibles au temps offrent les garanties suivantes du côté de l’implémentation.
  • Aucun chargement ni aucune initialisation à la demande n’est effectué.
  • Aucun appel ne franchit les limites d’une machine virtuelle ou d’un processus.
  • Les allocations de mémoire sont limitées.
Ainsi, les méthodes sécuritaires pour les threads sensibles au temps s’exécutent dans un temps constant avec les mêmes entrées et ne provoquent pas de pics de performances inattendus. De nombreuses méthodes du Microsoft Game Development Kit (GDK) sont marquées en interne comme sécuritaires pour les threads sensibles au temps, et il n’est pas nécessaire de marquer les threads comme sensibles au temps pour bénéficier de la garantie lors de l’appel de ces méthodes. La plupart des méthodes d’API asynchrones sont sécuritaires pour les threads sensibles au temps. Celles qui ne le sont pas concernent la configuration des files d’attente de tâches et d’autres appels peu fréquents qui sont généralement effectués au moment du chargement ou de l’initialisation. Toutes les méthodes liées au démarrage, à la gestion, à l’annulation, à l’achèvement ou à toute autre manipulation directe des tâches asynchrones sont sécuritaires pour les threads sensibles au temps. Pour plus d’informations sur les fonctions non sécuritaires, consultez la section Fonctions non sécuritaires pour les threads sensibles au temps de la rubrique Threads sensibles au temps.

Utilisation générique au-delà des appels d’API du Microsoft Game Development Kit (GDK)

Les bibliothèques asynchrones du Microsoft Game Development Kit (GDK) sont génériques et ne se limitent pas aux appels d’API. Tout appel asynchrone fourni par le Microsoft Game Development Kit (GDK) utilise les bibliothèques asynchrones en interne et fournit des méthodes cohérentes pour des actions telles que le démarrage de la tâche et l’obtention des résultats. Pour plus d’informations sur l’utilisation des bibliothèques à des fins autres que les API du GDK, consultez Exemple de code. Avec cette configuration, démarrer une tâche asynchrone suit le même processus, qu’il s’agisse d’une fonction du Microsoft Game Development Kit (GDK) ou d’un modèle personnalisé : un XAsyncBlock est configuré pour une tâche, puis la tâche est démarrée. Le démarrage de la tâche peut être une fonction d’API du Microsoft Game Development Kit (GDK) ou une méthode personnalisée du titre. N’hésitez pas à utiliser les bibliothèques asynchrones à toute fin asynchrone dans votre titre.

Documentation de référence de l’API

Voir aussi

Modèle de programmation asynchrone Conception de la file d’attente de tâches
Last modified on October 6, 2026