5

glib を使用して を介してシグナルをディスパッチする場合emit、すべての「リスナー」/ハンドラーが連続して呼び出されますか、または各リスナー/ハンドラーの後にイベント ループに制御が放棄されますか?

4

2 に答える 2

9

コールバックはすべて、メイン ループへの制御を放棄することなく連続して呼び出されます。

実際、私の知る限り、g_signal_emit() はすべてのハンドラーが呼び出されるまで制御を返さないため、メインループが起動する機会はありません。

したがって、この投稿のタイトルの質問に答えるには: いいえ、glib シグナルは非同期ではありません。

于 2010-01-28T04:05:57.537 に答える
5

GLib シグナルは、同期または非同期で処理できます。GObject シグナルは常に同期します。つまり、シグナルを発行すると、シグナルが処理されるまで戻りません。GLib でシグナルを非同期に処理するには (簡潔にするために vala を使用しています - コードをプレーンな C に変換するために vala コンパイラを使用します)、シグナル Source を定義するか、IdleSource や TimeoutSource などの定義済みのものを使用する必要があります ( I/O は問題外です)。たとえば、関数があるとします

void my_func() {
  stdout.puts("Hello world! (async)\n");
}

非同期で(同じスレッドから!)呼び出したい

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");
}

方法は次のとおりです。

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");
}

次の出力が得られます。

Hello world!
Hello world! (async)

my_func() 関数は、MainLoop がアイドル状態のときに実行されます (つまり、処理する他のシグナルがない)。特定の時間間隔が経過した後にトリガーするには、TimeoutSource 信号ソースを使用します。MainLoop が実行されている必要があります。そうでない場合、これは機能しません。

ドキュメンテーション:

于 2017-02-23T07:34:22.540 に答える