回调都是背靠背调用而不放弃对主循环的控制.
实际上,据我所知,g_signal_emit()甚至在调用所有处理程序之前都不会返回控制,因此主循环没有机会启动.
所以回答这篇文章标题中的问题:不,glib信号不是异步的.
小智 5
GLib 信号可以同步或异步处理。GObject 信号始终是同步的,即当您发出信号时,它在信号被处理之前不会返回。要使用 GLib 异步处理信号,(为了简洁,我使用 vala - 使用 vala 编译器将代码转换为纯 C),您必须定义一个信号源,或使用预定义的源,例如 IdleSource 或 TimeoutSource(当I/O 是不可能的)。例如假设你有一个函数
void my_func() {
stdout.puts("Hello world! (async)\n");
}
Run Code Online (Sandbox Code Playgroud)
并且你想异步调用它(从同一个线程!)
void caller() {
// Here you want to insert the asynchronous call
// that will be invoked AFTER caller has returned.
// Body of caller follows:
stdout.puts("Hello world!\n");
}
Run Code Online (Sandbox Code Playgroud)
这是你如何做到的:
void caller() {
// Code for the asynchronous call:
var ev = new IdleSource();
ev.set_callback(() => {
my_func();
return Source.REMOVE; // Source.REMOVE = false
});
ev.attach(MainContext.default());
// Body of caller follows:
stdout.puts("Hello world!\n");
}
Run Code Online (Sandbox Code Playgroud)
您将获得以下输出:
Hello world!
Hello world! (async)
Run Code Online (Sandbox Code Playgroud)
my_func() 函数将在 MainLoop 空闲时执行(即它没有其他信号要处理)。要在经过特定时间间隔后触发它,请使用 TimeoutSource 信号源。MainLoop 必须正在运行,否则这将不起作用。
文档: