Skip to main content
Cette rubrique présente les objectifs de conception fixés 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 kit de développement logiciel XBOX One, 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 par souci de 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 les leçons du précédent modèle asynchrone du kit de développement logiciel XBOX One et des commentaires des développeurs, la nouvelle solution du Microsoft Game Development Kit (GDK) vous donne un contrôle total sur la façon et l’endroit où les tâches asynchrones sont exécutées. Vous pouvez utiliser n’importe quelle conception de threading, qu’il s’agisse d’exécutions synchrones sur un seul thread ou d’exécutions parallèles sur des threads du titre avec des priorités et des masques d’affinité très spécifiques. Le kit de développement logiciel XBOX One utilisait uniquement le pool de threads système. Le changement de paradigme du Microsoft Game Development Kit (GDK) améliore la solution du kit de développement logiciel XBOX One 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) bénéficient d’une garantie de hautes performances.

Objectifs de conception

Les bibliothèques asynchrones sont conçues autour de quelques objectifs clés afin de garantir que les titres obtiennent les meilleures performances avec une surcharge minimale de l’API ou du système. La liste suivante présente quelques objectifs généraux.
  • Le code asynchrone est cohérent, 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 système liée à l’exécution des tâches est faible et compatible avec les threads principaux.
  • Les bibliothèques asynchrones ne doivent pas être réservées à 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 dans la section Améliorations par rapport au kit de développement logiciel XBOX One de cette rubrique.

Cohérent et multiplateforme

La cohérence implique notamment les 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.
Le caractère 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 bibliothèque fournit une méthode asynchrone, 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 total pour le développeur

Un aspect important des nouvelles bibliothèques asynchrones est que vous disposez d’un contrôle total pour permettre la meilleure utilisation possible pour le titre. Cela signifie que de nombreux éléments du modèle sont personnalisables, notamment les suivants. Lors de la création d’une file d’attente de tâches, 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 threading

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 threading et de simultanéité peuvent avoir lieu sans verrous. Les sections critiques, les opérations interverrouillées et les autres constructions multithread associées 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 de thread en fonction des 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 kit de développement logiciel XBOX One

Répondre à vos commentaires et améliorer les solutions passées 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 kit de développement logiciel XBOX One.

Fin de C++/CLI (WinRT)

Le kit de développement logiciel XBOX One exigeait l’utilisation de C++/CLI (WinRT) pour le comportement des fonctions asynchrones. Ainsi, le système gérait ses appels aux services XBOX et à d’autres services sans rencontrer de problèmes tels que des fuites de ressources et des erreurs. Toutefois, cela exigeait également d’apprendre une nouvelle syntaxe de code 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 les bibliothèques asynchrones à un modèle d’API de style C, à la manière de Win32. 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 système.

Contrôle total du comportement de threading

Le kit de développement logiciel XBOX One ne proposait qu’une seule façon de gérer les appels asynchrones : les exécuter simultanément sur les threads du pool système. Le contrôle se limitait à l’ajustement du pool de threads système. Dans le Microsoft Game Development Kit (GDK), le threading peut utiliser le pool de threads système comme dans le kit de développement logiciel XBOX One, ou être personnalisé avec un threading manuel pour construire le comportement adapté à l’application. Avec le threading manuel, 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 total pour 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 aucun autre usage à l’exécution. Vous pouvez utiliser votre propre gestion des exceptions dans votre titre. La plupart des erreurs et des codes d’état sont désormais signalés au moyen de codes HRESULT, dans le style de codage Win32 standard. Lorsque le code d’état du résultat n’est pas important, un booléen peut être utilisé. 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 spécifiques 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 garbage collection

Comme le Microsoft Game Development Kit (GDK) ne prend pas en charge C++/CLI (WinRT), cela signifie également qu’aucun garbage collection 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. Grâce aux handles, vous pouvez faire en sorte que le moment, le comportement et les performances des allocations/libérations soient gérés par l’appelant. Ces allocations et libérations peuvent être déplacées vers des threads de chargement auxiliaires pour éviter les à-coups de performances. La libération ne se produit pas de manière inattendue lorsque les performances sont primordiales. Toutefois, le suivi des ressources et la prévention des fuites de mémoire relèvent de 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 kit de développement logiciel XBOX One, avec son utilisation du framework COM managé, se prêtait à des problèmes de mémoire et de performances inattendus qui étaient parfois difficiles à prendre en compte. En revanche, le modèle du Microsoft Game Development Kit (GDK) garantit des performances et une empreinte mémoire cohérentes. Comme le threading peut être contrôlé, les performances des appels système sont plus faciles à inspecter à l’aide d’un profileur ou de code personnalisé. L’exemple ATG Asynchronous Programming comporte des tests intégrés qui mesurent une partie du temps passé. Le graphique de la figure 3 mesure le temps passé à gérer une tâche asynchrone avec un fournisseur asynchrone personnalisé. Les threads personnalisés utilisés pour le test exécutent les rappels aussi vite 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 système est très faible. Les coûts de surcharge surviennent principalement lors de l’attente des threads qui distribuent les ports de la file d’attente de tâches. Le temps global d’une tâche asynchrone, hors 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 doivent subir 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 de 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ûr pour les threads sensibles au temps ») déclenche une assertion de débogage. Ces méthodes sûres 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 n’est effectué au-delà des limites de machine virtuelle ou de processus.
  • Les allocations de mémoire sont limitées.
Ainsi, les méthodes sûres pour les threads sensibles au temps s’exécutent en 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ûres pour les threads sensibles au temps, et les threads n’ont pas besoin d’être marqués comme sensibles au temps pour bénéficier de cette garantie lors de l’appel de ces méthodes. La plupart des méthodes d’API asynchrones sont sûres 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 chargement ou à 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ûres pour les threads sensibles au temps. Pour plus d’informations sur les fonctions non sûres, consultez la section Fonctions non sûres 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, le démarrage d’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 à toutes fins asynchrones 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