> ## Documentation Index
> Fetch the complete documentation index at: https://devdocs.xbox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Guia de operações assíncronas do SDK C++ de Lobby e Matchmaking

> Entenda as operações assíncronas, a sondagem e as notificações de alteração de estado no SDK C++ de Lobby e Matchmaking do PlayFab, com práticas recomendadas para títulos multijogador.

# Operações e notificações assíncronas

Para operações que podem ser lentas ou computacionalmente caras, o SDK de Lobby e Matchmaking do PlayFab expõe APIs
assíncronas. As APIs assíncronas permitem iniciar operações caras ou lentas a partir dos seus threads principais e sondar
a conclusão dessas operações em um thread de sua escolha. Esse mesmo mecanismo de sondagem também é usado para entregar
notificações assíncronas de atualizações do SDK ao código do seu título. Esta página apresenta uma visão geral dos padrões de API
assíncrona do SDK de Lobby e Matchmaking do PlayFab e das práticas recomendadas para programar com eles.

## Padrões básicos de API

Há dois tipos de padrões de API assíncrona a serem considerados no SDK de Lobby e Matchmaking do PlayFab:

1. [Operações assíncronas](#asynchronous-operations)
2. [Notificações assíncronas](#asynchronous-notifications)

<a id="asynchronous-operations" />

### Operações assíncronas

É simples usar as APIs assíncronas do SDK. O padrão geral para iniciar e concluir operações
assíncronas é o seguinte:

1. Faça uma chamada de método normal à API assíncrona apropriada de sua escolha. As operações assíncronas comuns
   que você provavelmente usará incluem:
   * [PFMultiplayerCreateAndJoinLobby](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayercreateandjoinlobby).
   * [PFMultiplayerJoinLobby](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerjoinlobby).
   * [PFLobbyPostUpdate](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pflobbypostupdate).
   * [PFMultiplayerCreateMatchmakingTicket](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayercreatematchmakingticket).

2. Verifique o valor de retorno **HRESULT** da API com as macros **SUCCEEDED()** ou **FAILED()**. Esse valor retornado de forma
   síncrona informará se a operação foi iniciada com êxito.

<Warning>
  O valor de retorno síncrono de uma chamada de API assíncrona **NÃO** informa se a operação foi concluída com êxito. Para obter mais informações sobre erros síncronos e assíncronos, confira a [documentação de tratamento de erros](/pt-BR/services/playfab/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors#synchronous-vs-asynchronous-errors) do SDK.
</Warning>

3. Sonde a conclusão da operação assíncrona procurando a "alteração de estado de conclusão" associada à operação,
   que será fornecida por [PFMultiplayerStartProcessingLobbyStateChanges()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerstartprocessinglobbystatechanges)
   ou [PFMultiplayerStartProcessingMatchmakingStateChanges](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges).
   Um exemplo da "alteração de estado de conclusão" associada a **PFMultiplayerCreateAndJoinLobby()** é
   [PFLobbyCreateAndJoinLobbyCompletedStateChange](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/structs/pflobbycreateandjoinlobbycompletedstatechange).
   Informações mais detalhadas sobre o que são as "alterações de estado" e como elas funcionam podem ser encontradas na
   seção [Alterações de estado](#state-changes).

4. Verifique o valor **result** da alteração de estado de conclusão para determinar se a operação teve êxito ou falhou.
   Informações mais detalhadas sobre esses valores de erro podem ser encontradas na [documentação de tratamento de erros](/pt-BR/services/playfab/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors#synchronous-vs-asynchronous-errors) do SDK.

<a id="asynchronous-notifications" />

### Notificações assíncronas

Alguns recursos geram notificações assíncronas de alterações no SDK de Lobby e Matchmaking.

As notificações comuns incluem:

1. [Notificações de atualização do lobby](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/structs/pflobbyupdatedstatechange).
2. [Notificações de desconexão do lobby](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/structs/pflobbydisconnectingstatechange).
3. [Notificações de alteração de status do tíquete de matchmaking](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingticketstatuschangedstatechange).

Essas notificações assíncronas serão fornecidas a você pelo SDK como "alterações de estado" por meio de
[PFMultiplayerStartProcessingLobbyStateChanges()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerstartprocessinglobbystatechanges)
e [PFMultiplayerStartProcessingMatchmakingStateChanges](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges).

Informações mais detalhadas sobre o que são as "alterações de estado" e como elas funcionam podem ser encontradas na seção [Alterações de estado](#state-changes).

<a id="state-changes" />

## Alterações de estado

O modelo de API assíncrona do SDK de Lobby e Matchmaking é construído em torno das structs [PFLobbyStateChange](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/structs/pflobbystatechange)
e [PFMatchmakingStateChange](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/structs/pfmatchmakingstatechange).
As **PFLobbyStateChanges** notificam você sobre alterações no subsistema de lobby, e as **PFMatchmakingStateChanges**
notificam você sobre alterações no subsistema de matchmaking.

Essas "alterações de estado" são notificações assíncronas de eventos do SDK. Essas notificações são
enfileiradas internamente, e você as processa chamando [PFMultiplayerStartProcessingLobbyStateChanges()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pflobby/functions/pfmultiplayerstartprocessinglobbystatechanges)
e [PFMultiplayerStartProcessingMatchmakingStateChanges](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerstartprocessingmatchmakingstatechanges).
Essas funções retornarão todas as alterações de estado enfileiradas (do respectivo subsistema de API) como listas que você pode
percorrer e processar individualmente. Cada alteração de estado tem um campo *stateChangeType* correspondente que pode ser
inspecionado para determinar sobre qual alteração de estado específica você está sendo notificado. Depois de saber qual alteração de estado
você recebeu, poderá converter a struct genérica **PFLobbyStateChange** ou **PFMatchmakingStateChange** em
um tipo mais específico de struct de alteração de estado para inspecionar os dados específicos desse evento.

Normalmente, o processamento de alterações de estado é implementado como uma simples instrução switch que delega cada alteração de estado a um
manipulador.

Depois que a lista de alterações de estado de **PFMultiplayerStartProcessingLobbyStateChanges** ou **PFMultiplayerStartProcessingMatchmakingStateChanges** for processada,
ela precisará ser devolvida a [PFMultiplayerFinishProcessingMatchmakingStateChanges()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerfinishprocessingmatchmakingstatechanges)
ou [PFMultiplayerFinishProcessingMatchmakingStateChanges()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmatchmaking/functions/pfmultiplayerfinishprocessingmatchmakingstatechanges),
respectivamente.

```cpp theme={null}
//
// Process Lobby state changes
//
uint32_t lobbyStateChangeCount;
const PFLobbyStateChange * const * lobbyStateChanges;
HRESULT hr = PFMultiplayerStartProcessingLobbyStateChanges(m_pfmHandle, &lobbyStateChangeCount, &lobbyStateChanges);
if (FAILED(hr))
{
    return hr;
}

for (uint32_t i = 0; i < lobbyStateChangeCount; ++i)
{
    const PFLobbyStateChange* stateChange = lobbyStateChanges[i];
    switch (stateChange->stateChangeType)
    {
        case PFLobbyStateChangeType::CreateAndJoinLobbyCompleted:
        {
            HandleCreateAndJoinLobbyCompleted(
                static_cast<const PFLobbyCreateAndJoinLobbyCompletedStateChange*>(stateChange));
            break;
        }
        // add other state change handlers here
    }
}

hr = PFMultiplayerFinishProcessingLobbyStateChanges(m_pfmHandle, lobbyStateChangeCount, lobbyStateChanges);
if (FAILED(hr))
{
    return hr;
}

//
// Process Match state changes
//
uint32_t matchStateChangeCount;
const PFMatchmakingStateChange * const * matchStateChanges;
hr = PFMultiplayerStartProcessingMatchmakingStateChanges(m_pfmHandle, &matchStateChangeCount, &matchStateChanges);
if (FAILED(hr))
{
    return hr;
}

for (uint32_t i = 0; i < matchStateChangeCount; ++i)
{
    const PFMatchmakingStateChange* stateChange = matchStateChanges[i];
    switch (stateChange->stateChangeType)
    {
        case PFMatchmakingStateChangeType::TicketStatusChanged:
        {
            HandleMatchmakingTicketStatusChanged(
                static_cast<const PFMatchmakingTicketStatusChangedStateChange*>(stateChange));
            break;
        }
        // add other state change handlers here
    }
}

hr = PFMultiplayerFinishProcessingMatchmakingStateChanges(m_pfmHandle, matchStateChangeCount, matchStateChanges);
if (FAILED(hr))
{
    return hr;
}
```

## Contextos de operações assíncronas

Cada API assíncrona inclui um parâmetro `void* asyncContext`. Esse valor é um parâmetro de passagem que será definido
na alteração de estado de conclusão associada a essa chamada de API quando ela for fornecida por **PFMultiplayerStartProcessingLobbyStateChanges()**
ou **PFMultiplayerStartProcessingMatchmakingStateChanges()**.

Esse valor oferece um mecanismo para anexar contextos arbitrários, do tamanho de um ponteiro, às suas chamadas de API assíncrona. Esses
contextos podem ser usados em muitos cenários, incluindo:

1. associar dados específicos do título a uma chamada do SDK
2. vincular várias operações assíncronas com um identificador compartilhado

Esses contextos assíncronos não são obrigatórios para o uso do SDK, mas podem facilitar a escrita de parte da lógica do título.

## Enfileiramento de operações

Com frequência, ao trabalhar com APIs assíncronas, várias operações assíncronas precisam ser executadas sequencialmente como parte
de um fluxo assíncrono maior.

No SDK de Lobby e Matchmaking, um exemplo seria criar um lobby e enviar convites aos seus amigos para
esse lobby. De forma serializada, esse fluxo seria:

1. Chamar **PFMultiplayerCreateAndJoinLobby()** para criar um lobby do PlayFab e ingressar nele.
2. Aguardar a **PFLobbyCreateAndJoinLobbyCompletedStateChange** refletir que o lobby foi criado e ingressado com êxito.
3. Chamar **PFLobbySendInvite()** para cada amigo convidado.
4. Aguardar a **PFLobbySendInviteCompletedStateChange** refletir que o convite foi enviado com êxito.

Para fluxos e lógicas de título mais complicados, esse padrão serializado pode ser apropriado. No entanto, para fluxos mais simples,
o SDK oferece uma alternativa que pretende simplificar o código do título:

Muitas APIs assíncronas do SDK oferecem suporte ao enfileiramento de operações dependentes antes que uma operação anterior tenha
sido totalmente concluída. No exemplo anterior, você pode enviar um convite para um lobby antes de ver que
o lobby foi criado com êxito.

Efetivamente, o enfileiramento permite agrupar uma coleção de operações assíncronas, iniciá-las todas de uma vez
e consolidar o tratamento de erros em um único ponto de falha.

```cpp theme={null}
PFLobbyHandle newLobby;
HRESULT hr = PFMultiplayerCreateAndJoinLobby(m_pfmHandle, myPlayerEntityId, newLobbyConfiguration, nullptr, nullptr, &newLobby);
if (SUCCEEDED(hr))
{
    for (size_t i = 0; SUCCEEDED(hr) && i < friends.size(); ++i)
    {
        hr = PFLobbySendInvite(m_pfmHandle, myPlayerEntityId, friends[i], nullptr);
    }

    if (SUCCEEDED(hr))
    {
        m_lobby = newLobby;
        Log("Created lobby and invited %zu friends!", friends.size());
    }
    else
    {
        // For the purposes of demonstration, we could have a policy that we shouldn't bother with any lobbies where
        // we couldn't invite all of our friends.
        (void) PFLobbyLeave(newLobby, myPlayerEntityId, nullptr);
    }
}
```

## Controlar o trabalho assíncrono

Às vezes, é necessário que os títulos controlem onde o trabalho assíncrono é feito para evitar a contenção de CPU entre
bibliotecas e as cargas de trabalho principais de CPU do título.

O SDK de Lobby e Matchmaking permite controlar como o trabalho assíncrono é executado por meio do
[Controle da afinidade de thread](#controlling-thread-affinity)

<a id="controlling-thread-affinity" />

### Controle da afinidade de thread

Por padrão, o trabalho assíncrono do SDK é feito em threads em segundo plano cuidadosamente controlados. Alguns títulos precisam
de controle geral sobre *onde* esses threads em segundo plano são agendados para evitar a contenção de CPU.

Para esses títulos, o SDK de Lobby e Matchmaking fornece
[PFMultiplayerSetThreadAffinityMask()](/pt-BR/services/playfab/multiplayer/lobby/playfabmultiplayerreference-cpp/pfmultiplayer/functions/pfmultiplayersetthreadaffinitymask).
Nas plataformas compatíveis, isso permite limitar quais núcleos de CPU serão usados pelos threads em segundo plano do SDK.
Dessa forma, você pode garantir que determinados núcleos fiquem reservados para suas próprias cargas de trabalho de CPU, sem nenhuma contenção.


## Related topics

- [Tratar erros do SDK C++ de Lobby e Matchmaking](/pt-BR/services/playfab/multiplayer/lobby/lobby-and-matchmaking-client-sdk-errors.md)
- [Início rápido do SDK de Matchmaking](/pt-BR/services/playfab/multiplayer/matchmaking/quickstart-client-sdk.md)
- [SDKs de Lobby e Matchmaking do PlayFab](/pt-BR/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-sdks.md)
- [Rastreamento de diagnóstico nos SDKs de Lobby e Matchmaking do PlayFab](/pt-BR/services/playfab/multiplayer/lobby/lobby-matchmaking-sdks/lobby-matchmaking-logging.md)
- [Início rápido do SDK do Lobby](/pt-BR/services/playfab/multiplayer/lobby/lobby-getting-started.md)
