Skip to main content
异步 API 是一种快速返回但会启动异步任务的 API,并且结果会在任务完成后返回。 传统上,当使用完成回调时,游戏对哪个线程执行异步任务以及哪个线程返回结果几乎没有控制权。一些游戏被设计成堆的某一部分只由单个线程访问,以避免任何线程同步的需要。如果完成回调不是从游戏可控制的线程调用的,那么使用异步任务的结果更新共享状态就需要线程同步。 PlayFab Services SDK 提供了一个异步 C API,当进行异步 API 调用(例如 PFAuthenticationLoginWithCustomIDAsyncPFDataGetFilesAsyncPFProfilesGetProfileAsync)时,可以让开发人员直接控制线程。 以下是调用 PFProfilesGetProfileAsync 的基本示例:
要理解此调用模式,你需要了解如何使用 XAsyncBlockXTaskQueueHandle XAsyncBlock 承载与异步任务和完成回调相关的所有信息。 XTaskQueueHandle 允许你确定哪个线程执行异步任务,以及哪个线程调用 XAsyncBlock 的完成回调。

XAsyncBlock

让我们详细看看 XAsyncBlock。它是一个结构体,定义如下:
XAsyncBlock 包含:
  • queue - 一个 XTaskQueueHandle,它是一个句柄,表示关于在何处运行工作的信息。如果未设置此参数,则使用默认队列。
  • context - 允许你将数据传递给回调函数。
  • callback - 一个可选的回调函数,将在异步工作完成后被调用。如果不指定回调,可以使用 XAsyncGetStatus 等待 XAsyncBlock 完成,然后获取结果。
你应该为每次异步调用在堆上创建一个新的 XAsyncBlockXAsyncBlock 必须一直存在直到 XAsyncBlock 的完成回调被调用,然后才可以被删除。
重要: XAsyncBlock 必须保留在内存中,直到异步任务完成。如果它是动态分配的,可以在 XAsyncBlock 的完成回调内被删除。

等待异步任务

你可以通过两种不同的方式知道异步任务已完成:
  • XAsyncBlock 的完成回调被调用。
  • 使用 true 调用 XAsyncGetStatus 以等待它完成。
对于 XAsyncGetStatus,异步任务在 XAsyncBlock 的完成回调执行后才被认为已完成,但是 XAsyncBlock 的完成回调是可选的。 一旦异步任务完成,你可以获取结果。

获取异步任务的结果

要获取结果,大多数异步 API 函数都有一个对应的 Result 函数来接收异步调用的结果。 在我们的示例代码中,PFProfilesGetProfileAsync 有一个对应的 PFProfilesGetProfileGetResult 函数。你可以使用这个函数来检索该函数的结果并相应地采取行动。 有关检索结果的完整详细信息,请参阅每个异步 API 函数的文档。

XTaskQueueHandle

XTaskQueueHandle 允许你确定哪个线程执行异步任务,以及哪个线程调用 XAsyncBlock 的完成回调。 你可以通过设置调度模式来控制哪个线程执行这些操作。有三种可用的调度模式:
  • Manual - 手动队列不会自动调度。开发人员可以在他们想要的任何线程上调度它们。这可用于将异步调用的工作或回调端分配给特定线程。
  • Thread Pool - 使用线程池进行调度。线程池并行调用,当线程池线程可用时,轮流从队列中取一个调用来执行。Thread Pool 最容易使用,但对使用哪个线程的控制最少。
  • Serialized Thread Pool - 使用线程池进行调度。线程池串行调用,当单个线程池线程可用时,轮流从队列中取一个调用来执行。
  • Immediate - 立即在提交队列工作的线程上调度队列工作。
要创建一个新的 XTaskQueueHandle,你需要调用 XTaskQueueCreate。例如:
此函数接受两个 XTaskQueueDispatchMode 参数。XTaskQueueDispatchMode 有三个可能的值:
workDispatchMode 确定处理异步工作的线程的调度模式。completionDispatchMode 确定处理异步操作完成的线程的调度模式。 创建 XTaskQueueHandle 后,只需将其添加到 XAsyncBlock 即可控制你工作和完成函数上的线程。当你完成使用 XTaskQueueHandle 时(通常在游戏结束时),你可以使用 XTaskQueueCloseHandle 关闭它:
调用示例:

手动调度 XTaskQueueHandle

如果你为 XTaskQueueHandle 工作或完成队列使用了手动队列调度模式,则需要手动调度。假设创建了一个 XTaskQueueHandle,其中工作队列和完成队列都设置为手动调度,如下所示:
为了调度已被分配 XTaskQueueDispatchMode::Manual 的工作,请调用 XTaskQueueDispatch 函数。
调用示例:
  • queue - 要在哪个队列上调度工作。
  • port - XTaskQueuePort 枚举的一个实例。
  • timeoutInMs - 一个 uint32_t,以毫秒为单位的超时时间。
XTaskQueuePort 枚举定义了两种回调类型:

何时调用 XTaskQueueDispatch

为了检查队列何时收到新项目,你可以调用 XTaskQueueRegisterMonitor 来设置事件处理程序,让你的代码知道工作或完成已准备好调度。
XTaskQueueRegisterMonitor 接受以下参数:
  • queue - 你为其提交回调的异步队列。
  • callbackContext - 指向应传递给提交回调的数据的指针。
  • callback - 当新的回调被提交到队列时调用的函数。
  • token - 在稍后调用 XTaskQueueUnregisterMonitor 时使用的标记,用于删除回调。
例如,以下是对 XTaskQueueRegisterMonitor 的调用:
相应的 XTaskQueueMonitorCallback 回调可以如下实现:
然后在后台线程中,你可以监听此条件变量以唤醒并调用 XTaskQueueDispatch

参考

API 参考文档
最后修改于 2026年8月25日