任务队列 API 概述
任务队列是两个队列端口的组合:工作端口和完成端口。这些端口被绑定到同一个对象中,因为你通常两个都需要:工作端口用于执行异步工作,完成端口用于告知用户结果。 任务队列的描述如下。- 包含两个任务队列端口。
- 每个任务队列端口都可以有自己的分派模式,该模式决定队列中的项如何被分派。
- 分派模式从通过系统线程池完全自动分派,到必须显式移除任务的完全手动分派不等。
- 回调可以提交到队列的任一端口。
- 队列以句柄表示。句柄可以被复制,实际上会增加队列的引用计数。
- 线程池: 入队到线程池队列的回调在系统线程池上执行。线程池会并行调用这些回调,当线程池线程可用时依次从队列中取出一个调用来执行。
- 串行线程池: 回调入队并在线程池上运行,但一个接一个地运行,而不是在所有线程池线程上并行运行。
- 手动: 入队到手动队列的回调不会自动分派。由你决定在任何想要的线程上分派它们。如果你使用手动任务队列,必须确保你也同时泵送 Windows 消息队列。
- 立即: 立即分派模式根本不入队。它会立即在提交回调的线程上执行调用。
XTaskQueueDuplicateHandle、XTaskQueueSubmitCallback、XTaskQueueSubmitDelayedCallback 和 XTaskQueueCreateComposite 都会向队列句柄添加一个引用。这意味着队列在所有回调完成之前不会真正被销毁。
任务队列句柄是每个进程独立的资源,不能被封送或在进程外使用。
使用模式
任务队列的典型使用模式如下。- 创建一个任务队列句柄,然后为每个端口指定分派模式。
- 如果你使用手动分派,请建立应用程序特定的线程用于调用队列的分派函数。
-
将队列用作 Microsoft Game Development Kit (GDK) 调用的参数,或直接使用
XTaskQueueCallback提交。 - 或者,在应用关闭时终止任务队列。
异步任务队列操作指南主题
本节提供常见异步任务队列场景的操作指南示例。本节内容
创建线程池任务队列 提供了一个示例,展示如何创建一个在系统线程池上分派工作和完成回调的任务队列。 提交回调 提供了一个示例,展示如何将回调提交到任务队列的工作端口或完成端口。 复制任务队列句柄 提供了一个示例,展示如何复制任务队列句柄。如果你有长时间运行的工作,可能希望在工作持续期间复制任务队列句柄。这样,任何调用XTaskQueueCloseHandle 的人都不会在你仍然需要队列时将其关闭。
创建手动任务队列
提供了一个示例,展示如何创建一个手动泵送的任务队列。它创建了两个 STL 线程,分别为工作端口和完成端口分派调用。
使用事件控制手动队列分派
提供了一个示例,展示如何使用任务队列在队列中有可分派的项时发出条件变量信号。
将任务队列与 Windows 消息循环结合使用
提供了一个示例,使用线程池处理工作,但将完成端口回调集成到 Win32 窗口过程中。此示例还演示了将任务队列与其他线程模型集成时如何正确终止任务队列。
使用进程任务队列
提供了一个示例,展示如何使用进程任务队列。默认的进程任务队列同时使用线程池来分派工作和完成回调。
创建复合任务队列
提供了一个示例,使用线程池处理工作,但将完成端口回调集成到 Win32 WindowProc 回调函数中。此示例还演示了将任务队列与其他线程模型集成时如何正确终止任务队列。
使用延迟回调
提供了一个示例,展示如何使用延迟回调,每 500 毫秒调用 10 次回调。使用任务队列可通过 XTaskQueueSubmitDelayedCallback API 在将来提交回调。这样,你可以在失败的调用后稍作延迟再重试,或将其用作周期性事件的低成本计时器。
使用任务队列等待器
提供了一个示例,展示如何使用任务队列等待器。你可以将 Win32 内核句柄注册到任务队列。当该句柄变为已发出信号状态时,你的回调将被提交到队列。
