Pular para o conteúdo principal
Uma API assíncrona é uma API que retorna rapidamente, mas inicia uma tarefa assíncrona, e o resultado é retornado depois que a tarefa é concluída. Tradicionalmente, os jogos têm pouco controle sobre qual thread executa a tarefa assíncrona e qual thread retorna os resultados ao usar um callback de conclusão. Alguns jogos são projetados para que uma seção do heap seja acessada por apenas uma thread, a fim de evitar qualquer necessidade de sincronização de threads. Se o callback de conclusão não for chamado a partir de uma thread controlada pelo jogo, atualizar o estado compartilhado com o resultado de uma tarefa assíncrona exigirá sincronização de threads. A API C da XSAPI expõe uma nova API C assíncrona que dá aos desenvolvedores controle direto das threads ao fazer uma chamada a uma API assíncrona, como XblSocialGetSocialRelationshipsAsync(), XblProfileGetUserProfileAsync() e XblAchievementsGetAchievementsForTitleIdAsync(). Aqui está um exemplo básico que chama a API XblProfileGetUserProfileAsync:
Para entender esse padrão de chamada, você precisará entender como usar o XAsyncBlock e o XTaskQueueHandle.
  • O XAsyncBlock carrega todas as informações relacionadas à tarefa assíncrona e ao callback de conclusão.
  • O XTaskQueueHandle permite determinar qual thread executa a tarefa assíncrona e qual thread chama o callback de conclusão do XAsyncBlock.

O XAsyncBlock

Vamos examinar o XAsyncBlock em detalhes. Ele é uma struct definida da seguinte forma:
O XAsyncBlock contém:
  • queue - um XTaskQueueHandle, que é um identificador que representa informações sobre onde executar uma parte do trabalho. Se não for definido, uma fila padrão será usada.
  • context - permite passar dados para a função de callback.
  • callback - uma função de callback opcional que será chamada depois que o trabalho assíncrono for concluído. Se você não especificar um callback, poderá aguardar a conclusão do XAsyncBlock com XAsyncGetStatus e, em seguida, obter os resultados.
Você deve criar um novo XAsyncBlock no heap para cada API assíncrona que chamar. O XAsyncBlock precisa existir até que o callback de conclusão do XAsyncBlock seja chamado; depois disso, ele pode ser excluído.
Importante: Um XAsyncBlock precisa permanecer na memória até que a tarefa assíncrona seja concluída. Se ele for alocado dinamicamente, poderá ser excluído dentro do callback de conclusão do XAsyncBlock.

Aguardando uma tarefa assíncrona

Você pode saber que uma tarefa assíncrona foi concluída de várias maneiras diferentes:
  • O callback de conclusão do XAsyncBlock é chamado.
  • Chame XAsyncGetStatus com true para aguardar até que ela seja concluída.
Com XAsyncGetStatus, a tarefa assíncrona é considerada concluída depois que o callback de conclusão do XAsyncBlock é executado; no entanto, o callback de conclusão do XAsyncBlock é opcional. Depois que a tarefa assíncrona for concluída, você poderá obter os resultados.

Obtendo o resultado da tarefa assíncrona

Para obter o resultado, a maioria das funções de API assíncrona tem uma função [Nome da função]Result correspondente para receber o resultado da chamada assíncrona. No nosso código de exemplo, XblProfileGetUserProfileAsync tem uma função XblProfileGetUserProfileResult correspondente. Você pode usar essa função para recuperar o resultado da função e agir de acordo. Para obter detalhes completos sobre como recuperar resultados, consulte a documentação de cada função de API assíncrona.

O XTaskQueueHandle

O XTaskQueueHandle permite determinar qual thread executa a tarefa assíncrona e qual thread chama o callback de conclusão do XAsyncBlock. Você pode controlar qual thread executa essas operações definindo um modo de despacho. Há três modos de despacho disponíveis:
  • Manual - As filas manuais não são despachadas automaticamente. Cabe ao desenvolvedor despachá-las em qualquer thread que desejar. Isso pode ser usado para atribuir o lado de trabalho ou o lado de callback de uma chamada assíncrona a uma thread específica. Isso é discutido em mais detalhes abaixo.
  • Thread Pool - Despacha usando um pool de threads. O pool de threads invoca as chamadas em paralelo, retirando da fila uma chamada para executar à medida que as threads do pool ficam disponíveis. É o mais fácil de usar, mas oferece o menor controle sobre qual thread é usada.
  • Serialized Thread Pool - Despacha usando um pool de threads. O pool de threads invoca as chamadas em série, retirando da fila uma chamada para executar à medida que a única thread do pool fica disponível.
  • Immediate - Despacha imediatamente o trabalho enfileirado na thread a partir da qual ele foi enviado.
Para criar um novo XTaskQueueHandle, você precisará chamar XTaskQueueCreate. Por exemplo:
Essa função recebe dois parâmetros XTaskQueueDispatchMode. Há três valores possíveis para XTaskQueueDispatchMode:
workDispatchMode determina o modo de despacho da thread que processa o trabalho assíncrono, enquanto completionDispatchMode determina o modo de despacho da thread que processa a conclusão da operação assíncrona. Depois de criar seu XTaskQueueHandle, basta adicioná-lo ao XAsyncBlock para controlar as threads das suas funções de trabalho e de conclusão. Quando terminar de usar o XTaskQueueHandle, normalmente quando o jogo estiver terminando, você poderá fechá-lo com XTaskQueueCloseHandle:
Exemplo de chamada:

Despachando manualmente um XTaskQueueHandle

Se você usou o modo de despacho de fila manual para uma fila de trabalho ou de conclusão de um XTaskQueueHandle, precisará despachá-la manualmente. Digamos que um XTaskQueueHandle tenha sido criado com a fila de trabalho e a fila de conclusão definidas para despacho manual, assim:
Para despachar o trabalho que recebeu XTaskQueueDispatchMode::Manual, você precisará despachá-lo com a função XTaskQueueDispatch.
Exemplo de chamada
  • queue - a fila na qual o trabalho será despachado.
  • port - uma instância do enum XTaskQueuePort.
  • timeoutInMs - um uint32_t para o tempo limite em milissegundos.
Há dois tipos de callback definidos pelo enum XTaskQueuePort:

Quando chamar XTaskQueueDispatch

Para verificar quando a fila recebeu um novo item, você pode chamar XTaskQueueRegisterMonitor para definir um manipulador de eventos que informe ao seu código que há trabalhos ou conclusões prontos para serem despachados.
XTaskQueueRegisterMonitor recebe os seguintes parâmetros:
  • queue - a fila assíncrona para a qual você está enviando o callback.
  • callbackContext - um ponteiro para os dados que devem ser passados para o callback de envio.
  • callback - a função que será invocada quando um novo callback for enviado para a fila.
  • token - um token que será usado em uma chamada posterior a XTaskQueueUnregisterMonitor para remover o callback.
Por exemplo, aqui está uma chamada a XTaskQueueRegisterMonitor: XTaskQueueRegisterMonitor(queue, nullptr, HandleAsyncQueueCallback, &m_callbackToken); O callback XTaskQueueMonitorCallback correspondente pode ser implementado da seguinte forma:
Em seguida, em uma thread em segundo plano, você pode aguardar que essa variável de condição seja acionada e chamar XTaskQueueDispatch.

Confira também

Introdução às APIs C da XSAPI Referência da XSAPI libHttpClient
Última modificação em 8 de outubro de 2026