> ## 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.

# 事件管道教程

> 创建 PlayFab Services SDK 事件管道的分步教程:初始化、遥测密钥身份验证、发送事件、附加实体和关闭。

本文档是一个快速的分步教程,介绍如何使用 PlayFab Services SDK 中的事件管道功能。

## 步骤 1 - 初始化 PlayFab Services SDK

第一步是使用 [**PFServicesInitialize**](/services/playfab/api-references/c/pfservices/functions/pfservicesinitialize) 和 [**PFServiceConfigCreateHandle**](/services/playfab/api-references/c/pfserviceconfig/functions/pfserviceconfigcreatehandle) API 初始化 PF Service SDK。

**PFServiceConfigCreateHandle** API 接收一个连接字符串和一个可从 PlayFab Game Manager 上的游戏获得的 title ID。

第三个参数是一个 **PFServiceConfigHandle** 结构,表示正在创建的配置。此服务配置句柄将在下一步中使用。

```cpp theme={null}
PFServiceConfigHandle serviceConfigHandle;

PFServicesInitialize(nullptr);

PFServiceConfigCreateHandle(
    "titleConnectionString",
    "titleId",
    &serviceConfigHandle
);
```

## 步骤 2 - 创建遥测事件管道

接下来,让我们使用 [**PFEventPipelineCreateTelemetryPipelineHandleWithKey**](/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelinecreatetelemetrypipelinehandlewithkey) API 使用遥测密钥创建遥测事件管道。遥测密钥是通过 PlayFab Game Manager 创建和管理的。

创建 PFEventPipelineTelemetryKeyConfig 结构体时,我们传入实际的遥测密钥和 SDK 初始化时获得的服务配置句柄。

```cpp theme={null}
PFEventPipelineHandle handle;
XTaskQueueHandle taskQueueHandle;

XTaskQueueCreate(XTaskQueueDispatchMode::ThreadPool, XTaskQueueDispatchMode::Manual, &taskQueueHandle);

PFEventPipelineTelemetryKeyConfig telemetryKeyConfig
{
    "myTelemetryKey",
    serviceConfigHandle,
};

HRESULT hr = PFEventPipelineCreateTelemetryPipelineHandleWithKey(
    &telemetryKeyConfig,
    taskQueueHandle,
    nullptr,
    nullptr,
    nullptr,
    &handle
);

if (FAILED(hr))
{
    printf("Failed creating event pipeline: 0x%x\r\n", hr);
    return;
}
```

## 步骤 3 - 更新管道配置

让我们更新管道配置,在此示例中,我们希望发送最多 10 个事件的批次(默认值为 5)。

此外,由于我们将 maxWaitTimeInSeconds 和 pollDelayInMs 作为 null 指针发送,它们将使用相应管道类型的默认值。

我们还指定了"中"压缩级别,设置此属性可压缩正文有效负载,并有助于优化网络资源利用率。

然后,我们继续调用 [**PFEventPipelineUpdateConfiguration**](/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelineupdateconfiguration),传递从上一步获得的 **PFEventPipelineHandle** 和 **PFEventPipelineConfig** 结构。

```cpp theme={null}
uint32_t maxEvents = 10;
PFHCCompressionLevel compressionLevel = PFHCCompressionLevel::Medium;

PFEventPipelineConfig eventPipelineConfig
{
    &maxEvents,         // maxEventsPerBatch
    nullptr,            // maxWaitTimeInSeconds
    nullptr,            // pollDelayInMs
    &compressionLevel   // compressionLevel
};

HRESULT hr = PFEventPipelineUpdateConfiguration(
    handle,
    eventPipelineConfig
);

if (FAILED(hr))
{
    printf("Failed updating event pipeline configuration: 0x%x\r\n", hr);
    return;
};
```

## 步骤 4 - 发送事件

在这一步中,我们继续通过 [**PFEventPipelineEmitEvent**](/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelineemitevent) API 只发送一个名为 "TelemetryKeyEvent" 的事件。

由于我们到目前为止还没有提供实体身份验证,此事件未链接到任何实体。

```cpp theme={null}
PFEvent myEvent
{
    nullptr,
    "custom.playfab.events.PlayFab.Test.TelemetryEventPipelineTests",
    "TelemetryKeyEvent",
    nullptr,
    "{}"
};

HRESULT hr = PFEventPipelineEmitEvent(
    handle,
    &myEvent
);

if (FAILED(hr))
{
    printf("Failed emitting event: 0x%x\r\n", hr);
    return;
}
```

## 步骤 5 - 获取实体

这里,我们希望获取一个可用于开始将事件与其链接的实体。

在本教程中,我们调用 [**PFAuthenticationReLoginWithXUserAsync**](/services/playfab/api-references/c/pfauthentication/functions/pfauthenticationreloginwithxuserasync) API 以获取有效的 **PFEntityHandle**。

<Note>
  作为 **PFAuthenticationLoginWithXUserRequest** 一部分传递的 userHandle 对象是 XUserHandle 类型。如何获取有效的 XUserHandle 步骤超出本教程范围。有关此主题的更多信息,请参阅 [XUserAddAsync](/reference/system/xuser/functions/xuseraddasync) 文档。
</Note>

```cpp theme={null}
PFEntityHandle entityHandle;

PFAuthenticationLoginWithXUserRequest request{};
request.createAccount = true;
request.user = userHandle; // An XUserHandle obtained from XUserAddAsync

XAsyncBlock async{};

HRESULT hr = PFAuthenticationReLoginWithXUserAsync(entityHandle, &request, &async);

if (FAILED(hr))
{
    printf("Failed PFAuthenticationReLoginWithXUserAsync: 0x%x\r\n", hr);
    return;
}

hr = XAsyncGetStatus(&async, true); // This is doing a blocking wait for completion, but you can use the XAsyncBlock to set a callback instead for async style usage

if (FAILED(hr))
{
    printf("Failed XAsyncGetStatus: 0x%x\r\n", hr);
    return;
}
```

## 步骤 6 - 将实体添加到管道

由于我们已经获得了有效的实体,可以调用 [**PFEventPipelineAddUploadingEntity**](/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelineadduploadingentity),传入事件管道句柄和上一步中的实体句柄。这一操作允许管道切换为使用实体身份验证。

```cpp theme={null}
HRESULT hr = PFEventPipelineAddUploadingEntity(
    handle,
    entityHandle
);

if (FAILED(hr))
{
    printf("Failed adding uploading entity: 0x%x\r\n", hr);
    return;
}
```

## 步骤 7 - 发送事件

此过程与前面的事件提交相同。

唯一的两个区别是:

* 我们将此事件标记为不同的名称("EntityEvent")以使其更清晰。
* 此事件将被记录并与我们之前获取的实体链接。

```cpp theme={null}
PFEvent myEvent
{
    nullptr,
    "custom.playfab.events.PlayFab.Test.TelemetryEventPipelineTests",
    "EntityEvent",
    nullptr,
    "{}"
};

hr = PFEventPipelineEmitEvent(
    handle,
    &myEvent
);

if (FAILED(hr))
{
    printf("Failed emitting event: 0x%x\r\n", hr);
    return;
}
```

## 步骤 8 - 关闭事件管道句柄

最后,当我们完成事件上传后,唯一需要做的就是调用 [**PFEventPipelineCloseHandle**](/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelineclosehandle),传入我们的管道句柄。

```cpp theme={null}
PFEventPipelineCloseHandle(handle);
```

## 另请参阅

* [事件管道概述](/services/playfab/sdks/c/event-pipeline/eventpipeline)


## Related topics

- [PlayFab Services SDK - 事件管道](/zh-CN/services/playfab/sdks/c/event-pipeline/eventpipeline.md)
- [PlayFab 支持的语言](/zh-CN/services/playfab/sdks/languages/index.md)
- [Services C API overview - PFEventPipeline.h](/zh-CN/services/playfab/api-references/c/pfeventpipeline/pfeventpipeline_members.md)
- [PFEventPipelineCreatePlayStreamPipelineHandle](/zh-CN/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelinecreateplaystreampipelinehandle.md)
- [PFEventPipelineCreateTelemetryPipelineHandleWithEntity](/zh-CN/services/playfab/api-references/c/pfeventpipeline/functions/pfeventpipelinecreatetelemetrypipelinehandlewithentity.md)
