Passer au contenu principal
Une API asynchrone est une API qui rend la main rapidement, mais qui démarre une tâche asynchrone; le résultat est retourné une fois la tâche terminée. Traditionnellement, les jeux disposaient de peu de contrôle sur le thread qui exécute la tâche asynchrone et sur celui qui retourne les résultats lors de l’utilisation d’un rappel d’achèvement. Certains jeux sont conçus de sorte qu’une section du tas ne soit manipulée que par un seul thread, afin d’éviter tout besoin de synchronisation des threads. Si le rappel d’achèvement n’est pas appelé depuis un thread contrôlé par le jeu, la mise à jour de l’état partagé avec le résultat d’une tâche asynchrone nécessite une synchronisation des threads. L’API C de XSAPI expose une nouvelle API C asynchrone qui offre aux développeurs un contrôle direct des threads lors d’un appel d’API asynchrone, comme XblSocialGetSocialRelationshipsAsync(), XblProfileGetUserProfileAsync() et XblAchievementsGetAchievementsForTitleIdAsync(). Voici un exemple simple d’appel de l’API XblProfileGetUserProfileAsync :
Pour comprendre ce modèle d’appel, vous devez savoir comment utiliser XAsyncBlock et XTaskQueueHandle.
  • XAsyncBlock contient toutes les informations relatives à la tâche asynchrone et au rappel d’achèvement.
  • XTaskQueueHandle vous permet de déterminer quel thread exécute la tâche asynchrone et quel thread appelle le rappel d’achèvement de XAsyncBlock.

XAsyncBlock

Examinons XAsyncBlock en détail. Il s’agit d’une structure définie comme suit :
XAsyncBlock contient :
  • queue : un XTaskQueueHandle, c’est-à-dire un handle représentant des informations sur l’endroit où exécuter une unité de travail. S’il n’est pas défini, une file d’attente par défaut est utilisée.
  • context : vous permet de transmettre des données à la fonction de rappel.
  • callback : une fonction de rappel facultative qui est appelée une fois le travail asynchrone terminé. Si vous ne spécifiez pas de rappel, vous pouvez attendre la fin de XAsyncBlock avec XAsyncGetStatus, puis obtenir les résultats.
Vous devez créer un nouveau XAsyncBlock sur le tas pour chaque API asynchrone que vous appelez. Le XAsyncBlock doit rester en vie jusqu’à ce que son rappel d’achèvement soit appelé; il peut ensuite être supprimé.
Important : Un XAsyncBlock doit rester en mémoire jusqu’à la fin de la tâche asynchrone. S’il est alloué dynamiquement, il peut être supprimé dans le rappel d’achèvement de XAsyncBlock.

Attendre une tâche asynchrone

Vous pouvez savoir qu’une tâche asynchrone est terminée de plusieurs façons :
  • Le rappel d’achèvement de XAsyncBlock est appelé.
  • Appelez XAsyncGetStatus avec la valeur true pour attendre sa fin.
Avec XAsyncGetStatus, la tâche asynchrone est considérée comme terminée après l’exécution du rappel d’achèvement de XAsyncBlock; toutefois, ce rappel d’achèvement est facultatif. Une fois la tâche asynchrone terminée, vous pouvez obtenir les résultats.

Obtenir le résultat de la tâche asynchrone

Pour obtenir le résultat, la plupart des fonctions d’API asynchrones disposent d’une fonction [Nom de la fonction]Result correspondante qui reçoit le résultat de l’appel asynchrone. Dans notre exemple de code, XblProfileGetUserProfileAsync dispose d’une fonction XblProfileGetUserProfileResult correspondante. Vous pouvez utiliser cette fonction pour récupérer le résultat de la fonction et agir en conséquence. Pour plus de détails sur la récupération des résultats, consultez la documentation de chaque fonction d’API asynchrone.

XTaskQueueHandle

XTaskQueueHandle vous permet de déterminer quel thread exécute la tâche asynchrone et quel thread appelle le rappel d’achèvement de XAsyncBlock. Vous pouvez contrôler le thread qui effectue ces opérations en définissant un mode de distribution. Les modes de distribution suivants sont disponibles :
  • Manual : la file d’attente manuelle n’est pas distribuée automatiquement. C’est au développeur de distribuer les éléments sur le thread de son choix. Ce mode permet d’affecter le travail ou le rappel d’un appel asynchrone à un thread spécifique. Il est décrit plus en détail ci-dessous.
  • Thread Pool : distribue à l’aide d’un pool de threads. Le pool de threads appelle les éléments en parallèle, en prenant à tour de rôle un appel à exécuter dans la file d’attente à mesure que des threads du pool deviennent disponibles. C’est le mode le plus simple à utiliser, mais c’est celui qui vous donne le moins de contrôle sur le thread utilisé.
  • Serialized Thread Pool : distribue à l’aide d’un pool de threads. Le pool de threads appelle les éléments en série, en prenant à tour de rôle un appel à exécuter dans la file d’attente à mesure que l’unique thread du pool devient disponible.
  • Immediate : distribue immédiatement le travail mis en file d’attente sur le thread à partir duquel il a été soumis.
Pour créer un nouveau XTaskQueueHandle, vous devez appeler XTaskQueueCreate. Par exemple :
Cette fonction accepte deux paramètres XTaskQueueDispatchMode. Les valeurs possibles de XTaskQueueDispatchMode sont les suivantes :
workDispatchMode détermine le mode de distribution du thread qui gère le travail asynchrone, tandis que completionDispatchMode détermine le mode de distribution du thread qui gère l’achèvement de l’opération asynchrone. Une fois votre XTaskQueueHandle créé, ajoutez-le simplement au XAsyncBlock pour contrôler les threads de vos fonctions de travail et d’achèvement. Lorsque vous avez fini d’utiliser le XTaskQueueHandle, généralement à la fermeture du jeu, vous pouvez le fermer avec XTaskQueueCloseHandle :
Exemple d’appel :

Distribution manuelle d’un XTaskQueueHandle

Si vous avez utilisé le mode de distribution manuelle pour la file d’attente de travail ou d’achèvement d’un XTaskQueueHandle, vous devez effectuer la distribution manuellement. Supposons qu’un XTaskQueueHandle ait été créé avec la file d’attente de travail et la file d’attente d’achèvement toutes deux définies sur une distribution manuelle, comme ceci :
Pour distribuer le travail auquel XTaskQueueDispatchMode::Manual a été affecté, vous devez utiliser la fonction XTaskQueueDispatch.
Exemple d’appel
  • queue : la file d’attente sur laquelle distribuer le travail.
  • port : une instance de l’énumération XTaskQueuePort.
  • timeoutInMs : un uint32_t indiquant le délai d’expiration en millisecondes.
L’énumération XTaskQueuePort définit deux types de rappels :

Quand appeler XTaskQueueDispatch

Pour savoir quand la file d’attente a reçu un nouvel élément, vous pouvez appeler XTaskQueueRegisterMonitor afin de définir un gestionnaire d’événements qui indique à votre code que du travail ou des achèvements sont prêts à être distribués.
XTaskQueueRegisterMonitor accepte les paramètres suivants :
  • queue : la file d’attente asynchrone pour laquelle vous soumettez le rappel.
  • callbackContext : un pointeur vers les données à transmettre au rappel de soumission.
  • callback : la fonction appelée lorsqu’un nouveau rappel est soumis à la file d’attente.
  • token : un jeton utilisé ultérieurement lors d’un appel à XTaskQueueUnregisterMonitor pour supprimer le rappel.
Par exemple, voici un appel à XTaskQueueRegisterMonitor : XTaskQueueRegisterMonitor(queue, nullptr, HandleAsyncQueueCallback, &m_callbackToken); Le rappel XTaskQueueMonitorCallback correspondant peut être implémenté comme suit :
Ensuite, dans un thread d’arrière-plan, vous pouvez attendre le réveil de cette variable de condition et appeler XTaskQueueDispatch.

Voir aussi

Introduction aux API C de XSAPI Référence XSAPI libHttpClient
Dernière modification le 8 octobre 2026