Here is an example that shows two threads which take a long time to complete, but gracefully coordinate progress data to the gui. http://www.simsoup.info/SimSoup/GUI_With_Worker_Threads.html
The best part of this example is that it's in c++ and it demonstrates that your variables holding thread pointers and thread data don't have to be global. They can be held within classes in order to maintain some namespace organisation and reduce naming conflicts with variables and functions. Cheers :) David Marceau On 02/14/2014 09:51 PM, Valentin But wrote: > Greetings gtk-app-devel-list. > > I'm a newbie GTK+ developer and I have encountered with a problem. > > I tried to create a DC Motor Transient process calculation as a > practice programm for learning. > I've wanted to have a feedback of the calculation process on a progress bar. > 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. > > I don't adequate way to transfer status report from a thread, that > blocks a lot, for example very laggy socket connections. > > Here's a minimal programm. Somehow GTK+ calls from thread are working. > How sinfull is that? > > #include <stdlib.h> > #include <gtk/gtk.h> > > struct CallbackObject > { > GtkWidget *win; > GtkWidget *button; > GtkWidget *progress; > }; > > gpointer thread_func( struct CallbackObject *callobj ); > static void startstop_thread (GtkWidget *wid, struct CallbackObject *callobj); > > GThread *pthread = NULL; > gboolean thread_run = FALSE; > > const gchar *label_start = "Start thread"; > const gchar *label_stop = "Stop thread"; > > gpointer thread_func( struct CallbackObject *callobj ) > { > gdouble x = 0.0; > while (x < 1.0 && thread_run == TRUE) > { > usleep (20*1000); > x += 1.0 / 50; > > gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (callobj->progress), x); > } > > thread_run = FALSE; > pthread = NULL; > gtk_button_set_label (GTK_BUTTON (callobj->button), label_start); > > return NULL; > } > > static void startstop_thread (GtkWidget *wid, struct CallbackObject *callobj) > { > gpointer user_data = callobj; > > if (thread_run == FALSE) > { > thread_run = TRUE; > pthread = g_thread_new ("thread", (GThreadFunc) thread_func, user_data); > gtk_button_set_label (GTK_BUTTON (callobj->button), label_stop); > } > else > { > thread_run = FALSE; > g_thread_join (pthread); > pthread = NULL; > gtk_button_set_label (GTK_BUTTON (callobj->button), label_start); > } > } > > int main (int argc, char *argv[]) > { > GtkWidget *button = NULL; > GtkWidget *vbox = NULL; > struct CallbackObject *callobj = NULL; > > /* Initialize GTK+ */ > g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL); > gtk_init (&argc, &argv); > g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL); > > callobj = g_malloc (sizeof(struct CallbackObject)); > > /* Create the main window */ > callobj->win = gtk_window_new (GTK_WINDOW_TOPLEVEL); > gtk_container_set_border_width (GTK_CONTAINER (callobj->win), 8); > gtk_window_set_title (GTK_WINDOW (callobj->win), "GTK+-3.10.7-1 Threads"); > gtk_window_set_position (GTK_WINDOW (callobj->win), GTK_WIN_POS_CENTER); > gtk_widget_realize (callobj->win); > g_signal_connect (callobj->win, "destroy", gtk_main_quit, NULL); > > /* Create a vertical box with buttons */ > vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8); > gtk_container_add (GTK_CONTAINER (callobj->win), vbox); > > callobj->progress = gtk_progress_bar_new (); > gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (callobj->progress), TRUE); > gtk_box_pack_start (GTK_BOX (vbox), callobj->progress, TRUE, TRUE, 0); > > callobj->button = gtk_button_new_with_label ("Start thread"); > g_signal_connect (G_OBJECT (callobj->button), "clicked", G_CALLBACK > (startstop_thread), (gpointer) callobj); > gtk_box_pack_start (GTK_BOX (vbox), callobj->button, TRUE, TRUE, 0); > > button = gtk_button_new_with_label ("Close"); > g_signal_connect (button, "clicked", gtk_main_quit, NULL); > gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0); > > /* Enter the main loop */ > gtk_widget_show_all (callobj->win); > gtk_main (); > > g_free (callobj); > > return 0; > } > _______________________________________________ > gtk-app-devel-list mailing list > gtk-app-devel-list@gnome.org > https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list > _______________________________________________ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list