Attention: Here be dragons
This is the latest
(unstable) version of this documentation, which may document features
not available in or compatible with released stable versions of Godot.
Checking the stable version of the documentation...
WorkerThreadPool¶
继承: Object
单例,启动时会分配一些 Thread,可以将任务卸载到这些线程中执行。
描述¶
WorkerThreadPool 单例在项目启动时会分配一组 Thread(称作工作线程)并提供将任务卸载至这些线程上执行的方法。这样就能够简化多线程的使用,不必创建 Thread。
任务里放置的是要让线程执行的 Callable。WorkerThreadPool 既可以创建常规任务也可以创建分组任务,常规任务由单个工作线程执行,而分组任务可以分布在多个工作线程执行。分组任务会多次执行同一个 Callable,可用于遍历大量的元素,例如场景中的敌人。
以下是将开销很大的函数卸载到工作线程执行的例子:
var enemies = [] # 用敌人填充的数组。
func process_enemy_ai(enemy_index):
var processed_enemy = enemies[enemy_index]
# 开销很大的逻辑……
func _process(delta):
var task_id = WorkerThreadPool.add_group_task(process_enemy_ai, enemies.size())
# 其他代码……
WorkerThreadPool.wait_for_group_task_completion(task_id)
# 要求敌人 AI 已经处理完毕的其他代码。
private List<Node> _enemies = new List<Node>(); // 用敌人填充的数组。
private void ProcessEnemyAI(int enemyIndex)
{
Node processedEnemy = _enemies[enemyIndex];
// 开销很大的逻辑……
}
public override void _Process(double delta)
{
long taskId = WorkerThreadPool.AddGroupTask(Callable.From<int>(ProcessEnemyAI), _enemies.Count);
// 其他代码……
WorkerThreadPool.WaitForGroupTaskCompletion(taskId);
// 要求敌人 AI 已经处理完毕的其他代码。
}
以上代码要求 enemies
数组中的元素个数在多线程部分执行时保持不变。
注意:如果分布到多个线程执行的任务在计算方面的开销并不大,那么使用这个单例可能对性能有负面影响。
教程¶
方法¶
add_group_task ( Callable action, int elements, int tasks_needed=-1, bool high_priority=false, String description="" ) |
|
add_task ( Callable action, bool high_priority=false, String description="" ) |
|
get_group_processed_element_count ( int group_id ) const |
|
is_group_task_completed ( int group_id ) const |
|
is_task_completed ( int task_id ) const |
|
void |
wait_for_group_task_completion ( int group_id ) |
wait_for_task_completion ( int task_id ) |
方法说明¶
int add_group_task ( Callable action, int elements, int tasks_needed=-1, bool high_priority=false, String description="" )
将 action
添加为分组任务,能够被多个工作线程执行。该 Callable 的调用次数由 elements
决定,第一个调用的线程使用 0
作为参数,后续执行时会将其加 1,直到变为 element - 1
。
任务分布的线程数由 tasks_needed
定义,默认值 -1
表示分布到所有工作线程。high_priority
决定的是任务具有高优先级还是低优先级(默认)。你还可以选择提供 description
作为描述信息,方便调试。
返回分组任务 ID,可用于其他方法。
int add_task ( Callable action, bool high_priority=false, String description="" )
将 action
添加为分组任务,能够被单个工作线程执行。high_priority
决定的是任务具有高优先级还是低优先级(默认)。你还可以选择提供 description
作为描述信息,方便调试。
返回任务 ID,可用于其他方法。
int get_group_processed_element_count ( int group_id ) const
返回具有给定 ID 的分组任务的 Callable 已经被工作线程执行的次数。
注意:线程已经开始执行 Callable 但尚未完成的情况不计算在内。
bool is_group_task_completed ( int group_id ) const
如果具有给定 ID 的分组任务已经完成,则返回 true
。
bool is_task_completed ( int task_id ) const
如果具有给定 ID 的任务已经完成,则返回 true
。
void wait_for_group_task_completion ( int group_id )
在具有给定 ID 的分组任务完成前暂停调用这个方法的线程。
Error wait_for_task_completion ( int task_id )
暂停调用该方法的线程,直到给定 ID 对应的任务完成。
如果能够成功等待任务,则返回 @GlobalScope.OK。
如果不存在与传入 ID 对应的任务(可能已被等待或处理),则返回 @GlobalScope.ERR_INVALID_PARAMETER。
如果其他正在执行的任务调用了该方法,并且由于任务调度的原因,要等待的任务位于调用栈更下层的位置,因此无法继续,则返回 @GlobalScope.ERR_BUSY。这是比较高级的情况,只有任务之间存在依赖关系时才会出现。