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<Item> _enemies = new List<Item>(); // 一个用于填充敌人的数组。
private void ProcessEnemyAI(int enemyIndex)
{
Item processedEnemy = _enemies[enemyIndex];
}
public override void _Process(double delta)
{
long taskId = WorkerThreadPool.AddGroupTask(Callable.From<int>(ProcessEnemyAI), _enemies.Count);
// 其他代码...
WorkerThreadPool.WaitForGroupTaskCompletion(taskId);
// 取决于敌人AI的其他代码已经处理。
}
上述代码依赖于在多线程处理部分中,enemies数组中的元素数量保持不变。 Note: 如果在各线程之间分配的任务在计算量上并非很大,那么使用这个单例模式可能会对性能产生负面影响
方法¶
add_group_task(action: Callable, elements: int, tasks_needed: int = -1, high_priority: bool = false, description: String = "") |
|
add_task(action: Callable, high_priority: bool = false, description: String = "") |
|
get_group_processed_element_count(group_id: int) const |
|
is_group_task_completed(group_id: int) const |
|
is_task_completed(task_id: int) const |
|
void |
wait_for_group_task_completion(group_id: int) |
wait_for_task_completion(task_id: int) |
方法说明¶
int add_group_task(action: Callable, elements: int, tasks_needed: int = -1, high_priority: bool = false, description: String = "") 🔗
将action添加为要由工作线程执行的组任务。Callable将根据elements被多次调用,第一个线程以值0作为参数调用它,并且每次连续执行将该值递增1,直到它到达元素-1。
任务分配到的线程数由tasks_needed定义,其中默认值-1表示它被分配到所有工作线程。high_priority确定任务是高优先级还是低优先级(默认)。您可以选择提供description来帮助调试。
返回可由其他方法使用的组任务ID。
警告:必须在某个时候使用wait_for_task_completion()或wait_for_group_task_completion()等待每个任务完成,以便清理任务中分配的任何资源。
int add_task(action: Callable, high_priority: bool = false, description: String = "") 🔗
将action添加为要由工作线程执行的任务。high_priority确定任务是高优先级还是低优先级(默认)。您可以选择提供description来帮助调试。
返回可由其他方法使用的任务ID。
警告:必须在某个时候使用wait_for_task_completion()或wait_for_group_task_completion()等待每个任务完成,以便清理任务中分配的任何资源。
int get_group_processed_element_count(group_id: int) const 🔗
返回具有给定ID的组任务的Callable已被工作线程执行的次数。
注意:如果一个线程已经开始执行Callable但尚未完成,则不会被计算在内。
bool is_group_task_completed(group_id: int) const 🔗
如果具有给定ID的组任务完成,则返回true。
注意:您应该只在添加组任务和等待其完成之间调用此方法。
bool is_task_completed(task_id: int) const 🔗
如果具有给定ID的任务已完成,则返回true。
注意:您应该只在添加任务和等待任务完成之间调用此方法。
void wait_for_group_task_completion(group_id: int) 🔗
暂停调用此方法的线程,直到具有给定ID的组任务完成。
Error wait_for_task_completion(task_id: int) 🔗
暂停调用此方法的线程,直到具有给定ID的任务完成。
如果可以成功等待任务,则返回@GlobalScope.OK。
如果具有传递ID的任务不存在(可能是因为它已经被等待和处理),则返回@GlobalScope.ERR_INVALID_PARAMETER。
如果调用是从另一个正在运行的任务发出的,并且由于任务调度,有可能死锁(例如,要等待的任务可能在调用堆栈中的较低级别,因此无法继续)。这是一种高级情况,只有当一些任务依赖于其他任务时才会重要(在当前实现中,棘手的情况是试图等待旧任务的任务)。