являются бойкими сигналами асинхронными? - PullRequest
2 голосов
/ 28 января 2010

При использовании glib для отправки сигналов через emit все ли «слушатели» / обработчики называются «спина к спине» или , передается ли управление в цикл событий после каждого слушателя / обработчика? *

Ответы [ 2 ]

5 голосов
/ 28 января 2010

Все обратные вызовы вызываются спина к спине без передачи управления в основной цикл.

На самом деле, насколько мне известно, g_signal_emit () даже не возвращает управление до тех пор, пока не будут вызваны все обработчики, поэтому у основного цикла нет возможности запустить его.

Итак, чтобы ответить на вопрос в заголовке этого поста: нет, бойкие сигналы не асинхронны.

2 голосов
/ 23 февраля 2017

GLib сигналы могут обрабатываться синхронно или асинхронно. Сигналы GObject всегда являются синхронными, то есть, когда вы излучаете сигнал, он не возвращается, пока сигнал не будет обработан. Чтобы асинхронно обрабатывать сигнал с помощью GLib (я использую vala для краткости - используйте компилятор vala для преобразования кода в простой C), вы должны определить источник сигнала или использовать предопределенный, например IdleSource или TimeoutSource (когда Ввод / вывод исключен). Например, предположим, что у вас есть функция

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 должен быть запущен, иначе это не будет работать.

Документация:

...