Godot Version
4.2
Question
I try to offload some work to thread and get signal on finish, but get error when signaling from thread:
- Implemented part in C++
WorkerThreadPool::TaskID GDExample::run_pool() {
this->connect("task_completed", callable_mp(this, &GDExample::task123_completed), CONNECT_DEFERRED); // , CONNECT_DEFERRED !
auto call = callable_mp(this, &GDExample::task123).bind(777);
auto id = WorkerThreadPool::get_singleton()->add_task(call);
return id;
}
bool GDExample::check_pool(WorkerThreadPool::TaskID id) {
auto err = WorkerThreadPool::get_singleton()->wait_for_task_completion(id);
return err == Error::OK;
}
void GDExample::task123(int i) {
//set_current_thread_safe_for_nodes(true);
UtilityFunctions::print("task123 ", i);
emit_signal("task_completed", i);
}
void GDExample::task123_completed(int par) {
UtilityFunctions::print("task123 completed", par);
}
- Registered function in bind:
ClassDB::bind_method(D_METHOD("run_pool"), &GDExample::run_pool);
ClassDB::bind_method(D_METHOD("check_pool"), &GDExample::check_pool);
ClassDB::bind_method(D_METHOD("task123_completed"), &GDExample::task123_completed);
- And call from GDScript:
func _ready():
var id = run_pool()
var res = check_pool(id)
Everything works as expected except signal:
E 0:00:01:0617 emit_signalp: Caller thread can't call this function in this node (/root/Node2D/GDExample). Use call_deferred() or call_thread_group() instead.
<C++ Error> Condition "!is_accessible_from_caller_thread()" is true. Returning: (ERR_INVALID_PARAMETER)
<C++ Source> scene/main/node.cpp:3638 @ emit_signalp()
This message came from ERR_THREAD_GUARD, which uses is_accessible_from_caller_thread(), which check is my node not in tree or is_current_thread_safe_for_nodes().
So questions are:
- Is it possible emit_signal on main thread (I believe CONNECT_DEFERRED was made for that) ?
- And how to mark thread safe for node if set_current_thread_safe_for_nodes(bool) is not exposed ? I see many usage of this function in godot sources.
Thank you.