Re: GUI signals from a thread (GTK+-3.10)



On Fri, Feb 14, 2014 at 6:51 PM, Valentin But <valentin but eesti ee> wrote:
Greetings gtk-app-devel-list.

I'm a newbie GTK+ developer and I have encountered with a problem.
Hello and welcome!

Documentation say that "the threading support has been deprecated in
GTK+ 3.6. Instead of calling GTK+ directly from multiple threads, it
is recommended to use g_idle_add(), g_main_context_invoke() and
similar functions to make these calls from the main thread instead".

I have no idea how g_main_context_invoke() could be usefull for that
and g_idle_add() is totally wrong: because if something heavy in the
function happens, then the GUI hangs anyway.

This section of the documentation could be more explicit. The key
point about g_idle_add() is that it is safe to call from another
thread. Its purpose is not to perform blocking or "heavy" operations,
but instead to be a threadsafe method by which you can return
information to the main loop.

Here's a minimal programm. Somehow GTK+ calls from thread are working.
How sinfull is that?
It is fully sinful and few will pardon it! ;) It
"works"--sometimes--on your platform. The fact is that you are open to
segfaults or other spurious behavior.

While I don't have time to rewrite your program, here's the basic
outline of how it should work:
You should define small struct like struct progress_info {
GtkProgressBar* bar; gdouble fraction; }.
You should create a new function called something like
threadfunc_cb(gpointer userdata) that casts userdata to a struct
progress_info*, and then calls gtk_progress_bar_set_fraction() with
the information inside the struct. Be sure to return G_SOURCE_REMOVE,
and also g_free() the userdata.
Inside your threadfunc() should g_malloc a struct progress_info called
something like m_progress_info and set its parameters accordingly.
Then you should call g_idle_add(threadfunc_cb, m_progress_info).

With g_idle_add_full() you can specify a GDestroyNotify callback to
free your data automatically! Instead of calling g_free() in your
threadfunc_cb, you can use:
g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, threadfunc_cb,
m_progress_info, g_free);

I looked around for example code on developer.gnome.org but came up
empty handed. Nonetheless, I'm pretty sure this mailing list has a ton
of old threads on the correct usage of g_idle_add(). :)

Have fun with your project!


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]