glib信号异步?

jld*_*ont 4 asynchronous signals gnome glib

当使用glib来发送信号时emit,是否所有"侦听器"/处理程序都是背靠背调用,或者是在每个侦听器/处理程序之后将控件放弃到事件循环中?

jst*_*ast 6

回调都是背靠背调用而不放弃对主循环的控制.

实际上,据我所知,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 必须正在运行,否则这将不起作用。

文档: