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

# 設定自訂提供者範例

> 使用 XAsyncBegin 和提供者回呼撰寫自訂非同步提供者，處理工作的 Begin、Cleanup、GetResult、DoWork 和 Cancel 案例。

本主題提供如何設定自訂非同步提供者的範例。撰寫自訂非同步提供者時，非同步方法會透過
呼叫 [XAsyncBegin](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncbegin.md) 來啟動。此函式具有一個回呼
參數，用於實作例如狀態變更的處理、將回呼加入佇列，
以及觸發完成等功能。

```c++ theme={null}
struct Context
{
    uint64_t result;
};

Context* context = new Context{ 0 };
// Assume that the async block is already filled out with the completion callback and task queue.
HRESULT hr = XAsyncBegin(async, context, ProviderFuncIdentity, __FUNCTION__,
    [](XAsyncOp op, const XAsyncProviderData* providerData)
    {
        Context* context =
        reinterpret_cast<Context*>(providerData->context);
        switch (op)
        {
            case XAsyncOp::Begin:
                return XAsyncSchedule(providerData->async, 0);

            case XAsyncOp::Cleanup:
                delete context;
                break;

            case XAsyncOp::GetResult:
                memcpy(providerData->buffer, &context->result, sizeof(uint64_t));
                break;

            case XAsyncOp::DoWork:
                context->result = 12345678;
                XAsyncComplete(providerData->async, S_OK, sizeof(uint64_t));
                break;

            case XAsyncOp::Cancel:
                // This call can't be canceled.
                break;
        }

    return S_OK;
});
```

這裡有許多內容需要說明，但基本概念很簡單：
呼叫 `XAsyncBegin`，並提供一個[提供者回呼](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncprovider.md)
來處理不同的狀態變更。請回想一下，非同步
區塊包含要使用的工作佇列以及選用的
完成回呼實作。接著，回呼必須處理非同步工作執行階段的[五種不同
案例](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/enums/xasyncop.md)，如下表所示。

| 提供者案例 | 職責 |
| - | - |
| `Begin` | 由 `XAsyncBegin` 的呼叫立即呼叫。此案例負責將非同步工作回呼排程到工作佇列上。這是透過呼叫 [XAsyncSchedule](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncschedule.md) 來處理。它會將此回呼加入佇列，以透過工作佇列的工作連接埠，以 `DoWork` 案例再次執行。 |
| `Cleanup` | 在非同步工作即將完成時呼叫，此時可刪除為追蹤而建立的任何內部資料。在前述範例程式碼中，此案例會清除為追蹤結果資料而配置的 `Context` 結構。 |
| `GetResult` | 在使用者呼叫 [XAsyncGetResult](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncgetresult.md) 時呼叫。接著，此案例必須寫入傳遞給此案例的輸出緩衝區。因此，原始的非同步結果必須已儲存在某處。前述範例程式碼將其儲存在 `Context` 結構中。 從非同步工作傳回資料的非同步 Microsoft Game Development Kit (GDK) API 函式，會在內部呼叫 `XAsyncGetResult`，並將該資料轉換為適合呼叫端的形式。我們建議使用此方式來處理結果。 |
| `DoWork` | 透過已分派其工作連接埠的工作佇列呼叫。這表示此回呼的堆疊框架會依據工作佇列的設定方式，在預期的執行緒上執行。任何工作都應在此執行。 在 [XAsyncRun](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasyncrun.md) 的內部非同步提供者實作中，這是它執行傳入之工作回呼的位置。對於自訂提供者，工作可以直接在回呼中完成，或使用某種自訂方法來封裝功能。 工作完成時，必須呼叫 [XAsyncComplete](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasynccomplete.md)。此函式會執行兩項工作。首先，它會藉由提供資料大小來指定是否需要任何輸出資料。如果提供大於零的值，就會配置內部緩衝區供 `GetResult` 案例寫入。其次，它會將完成回呼的呼叫加入佇列，以在工作佇列的完成連接埠上執行。傳遞給 `XAsyncComplete` 的完成狀態碼，會成為呼叫 [XAsyncGetStatus](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasyncgetstatus.md) 時傳回的代碼。 |
| `Cancel` | 由外部呼叫 [XAsyncCancel](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasynccancel.md) 觸發。如果未實作此案例，則不會發生任何事。若要允許取消，提供者必須能夠向任何正在執行的工作發出停止訊號。接著，`DoWork` 案例必須以 `E_ABORT` 狀態呼叫 `XAsyncComplete`。 |

## 參考 API 文件

* [XAsyncProvider (API 內容)](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/xasyncprovider_members.md)
  * 函式
    * [XAsyncBegin](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncbegin.md)
    * [xasyncprovider](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncprovider.md)
    * [XAsyncSchedule](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncschedule.md)
    * [XAsyncGetResult](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasyncgetresult.md)
    * [XAsyncComplete](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/functions/xasynccomplete.md)
* [xasync (API 內容)](https://docs.xbox.com/zh-TW/reference/system/xasync/xasync_members.md)
  * 函式
    * [XAsyncRun](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasyncrun.md)
    * [XAsyncGetStatus](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasyncgetstatus.md)
    * [XAsyncCancel](https://docs.xbox.com/zh-TW/reference/system/xasync/functions/xasynccancel.md)

## 另請參閱

[XAsyncProvider 程式庫概觀](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider.md)

[設定叫用方法 (範例)](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-invocation-methods.md)

[設定傳回資料 (範例)](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-return-data.md)

[設定可取消性 (範例)](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-cancelability.md)

[XAsyncProvider](https://docs.xbox.com/zh-TW/reference/system/xasyncprovider/xasyncprovider_members.md)


## Related topics

- [用於非同步工作程式設計的 XAsync 程式庫](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/index.md)
- [設定傳回資料範例](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-return-data.md)
- [設定可取消性範例](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-cancelability.md)
- [設定叫用方法範例](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider-example-setup-invocation-methods.md)
- [XAsyncProvider 程式庫概觀](https://docs.xbox.com/zh-TW/build/core-features/common/async/async-libraries/async-library-xasyncprovider.md)
