Search code examples
cgtk3glibgobject

Emit signal from separate thread in glib/gtk


I've programmed a GTK3 application in C. To speed up performance I want to put some calculations in separate threads. Currently I have not yet decided how to exactly implement it. But I think I will go with a GTask that I will trigger to run in a separate thread.

I want to to emit certain status updates about the calculation progress on my GUI.

They way I imagine this:

I've got a calculation GObject with a do_the_stuff_async() function that triggers the thread/GTask. Ideally, I want to connect to a 'progress-changed' signal which gives me the current status that I can display on my GUI. Also it would be great to trigger an event once the task has finished, which seems doable with a GTask

How do I safely emit a signal from a GTask/GThread to my GTK main loop?

Because I have not yet started implementing the asynchronous stuff: Is a GTask a suitable way for this or should I use something entirely different?


Solution

  • A GTask is suitable for this.

    To emit the signal in a different thread:

    1. Store the GMainContext of the main thread somewhere, and pass it into the GTask as task data.
    2. When you want to emit a signal, create a GSource with g_idle_source_new(), add a callback for it, and attach it to the GMainContext of the main thread. That will make the callback be called in the main thread the next time the main thread’s context iterates.
    3. The callback should call g_signal_emit() as appropriate.

    Unless you want to make the GObject that you’re emitting the signal from thread safe, you should not pass it to the GTask worker thread. My general advice would be to avoid locking by only passing immutable objects to and from the worker thread.

    Note that you could use g_idle_add() to create an idle GSource and add it to the global default GMainContext (the one GTK uses in the main thread). However, this makes the use of the GMainContext less explicit, and hence makes the code less maintainable. It’s not an approach which I would recommend in general.