Skip to main content
异步 API 是一种快速返回但启动异步任务的 API,其结果会在任务完成后返回。 传统上,游戏在使用完成回调时对于哪个线程执行异步任务以及哪个线程返回结果几乎没有控制权。有些游戏被设计为堆的某个部分只由单个线程访问,以避免需要线程同步。如果完成回调不是从游戏控制的线程中调用的,则用异步任务的结果更新共享状态将需要线程同步。 XSAPI C API 公开了一个新的异步 C API,该 API 使开发人员在进行异步 API 调用时可以直接控制线程,例如 XblSocialGetSocialRelationshipsAsync()XblProfileGetUserProfileAsync()XblAchievementsGetAchievementsForTitleIdAsync() 以下是一个调用 XblProfileGetUserProfileAsync API 的基本示例:
要理解此调用模式,你需要了解如何使用 XAsyncBlockXTaskQueueHandle
  • XAsyncBlock 携带与异步任务完成回调相关的所有信息。
  • XTaskQueueHandle 允许你确定哪个线程执行异步任务以及哪个线程调用 XAsyncBlock 的完成回调

XAsyncBlock

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

等待异步任务

你可以通过多种不同的方式确定异步任务是否完成:
  • XAsyncBlock 的完成回调被调用。
  • 使用 true 调用 XAsyncGetStatus 以等待其完成。
使用 XAsyncGetStatus 时,异步任务在 XAsyncBlock 的完成回调执行后被视为完成,但 XAsyncBlock 的完成回调是可选的。 一旦异步任务完成,你就可以获取结果。

获取异步任务的结果

要获取结果,大多数异步 API 函数都有一个对应的 [函数名]Result 函数,用于接收异步调用的结果。 在我们的示例代码中,XblProfileGetUserProfileAsync 有一个对应的 XblProfileGetUserProfileResult 函数。你可以使用此函数检索函数的结果并采取相应的操作。 有关检索结果的完整详细信息,请参阅每个异步 API 函数的文档。

XTaskQueueHandle

XTaskQueueHandle 允许你确定哪个线程执行异步任务以及哪个线程调用 XAsyncBlock 的完成回调 你可以通过设置分派模式来控制哪个线程执行这些操作。有三种分派模式可用:
  • Manual - 手动队列不会自动分派。开发人员可以在他们想要的任何线程上分派它们。这可以用于将异步调用的工作端或回调端分配给特定线程。这将在下面更详细地讨论。
  • 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 的调用: XTaskQueueRegisterMonitor(queue, nullptr, HandleAsyncQueueCallback, &m_callbackToken); 对应的 XTaskQueueMonitorCallback 回调可以按如下方式实现:
然后在后台线程中,你可以监听此条件变量以唤醒并调用 XTaskQueueDispatch

另请参阅

XSAPI C API 简介 XSAPI 参考 libHttpClient
最后修改于 2026年8月25日