GNOME Bugzilla – Bug 388304
[Win32] Create widget dynamically in a gthread
Last modified: 2006-12-21 18:55:47 UTC
Steps to reproduce: 1. Create a notebook with textview and treeview, a gthread 2. in the thread create new page for notebook with textview and treeview in 3. The programm crash in win32 (maybe the mutex of gtk_thread) Stack trace: /* * Compile with: * * @g++ -Wall -o gtk-thread main.cpp `pkg-config --cflags --libs gtk+-2.0 gthread-2.0` * * */ #ifndef __linux__ #pragma comment(lib, "gtk-win32-2.0.lib") #pragma comment(lib, "gdk-win32-2.0.lib") #pragma comment(lib, "glib-2.0.lib") #pragma comment(lib, "gobject-2.0.lib") #pragma comment(lib, "gthread-2.0.lib") #endif #include <iostream> #ifndef __linux__ #include <windows.h> #endif #include <gtk/gtk.h> #include <glib/gprintf.h> typedef struct { GtkWidget *noteBook; } WidgetNoteBook; void addPage(GtkWidget * notebook, const char *name); /* enter GTK thread lock */ inline void enter() { gdk_threads_enter(); }; /* release GTK thread lock */ inline void leave() { gdk_flush(); gdk_threads_leave(); }; void destroy(GtkWidget *widget, gpointer data) { gtk_main_quit(); } GtkWidget *object = NULL; void OnClicked(GtkWidget *pButton, gpointer data) { GtkWidget * notebook = (GtkWidget*)data; addPage((GtkWidget *)notebook, "Other"); } /*void attente(const char *name) { if(strcmp(name, "Thread") == 0) { //leave(); while (gtk_events_pending()) { gtk_main_iteration(); } //enter(); } }*/ void *argument_thread(void *args) { WidgetNoteBook *data = (WidgetNoteBook *)args; while(1) { /*while (gtk_events_pending ()) { gtk_main_iteration (); }*/ /* sleep a while */ #ifndef __linux__ Sleep(g_random_int_range (1000, 4000)); #else sleep(g_random_int_range (1, 4)); #endif enter(); //gtk_signal_emit_by_name( (GtkObject*)(object), "clicked", (gpointer)data->noteBook ); //addPage((GtkWidget *)data->noteBook, "Thread"); //attente("Thread"); leave(); } return NULL; } void addPage(GtkWidget * notebook, const char *name) { if(notebook) { GtkWidget *pHBox; pHBox = gtk_hbox_new(FALSE, 5); gtk_widget_show(pHBox); // Textview GtkWidget *pScrolled; GtkWidget *pTextView; pScrolled = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(pScrolled); pTextView=gtk_text_view_new(); gtk_widget_show(pTextView); gtk_text_view_set_editable(GTK_TEXT_VIEW(pTextView), FALSE); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (pScrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pScrolled), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(pScrolled), pTextView); // Liste GtkWidget *pListView; GtkWidget *pScrollbar; GtkListStore *pListStore; GtkTreeViewColumn *pColumn; GtkCellRenderer *pCellRenderer; pListStore = gtk_list_store_new(1, G_TYPE_STRING); pListView = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pListStore)); gtk_widget_show(pListView); gtk_widget_set_size_request(pListView, 120, -1); pCellRenderer = gtk_cell_renderer_text_new(); pColumn = gtk_tree_view_column_new_with_attributes("Utilisateurs", pCellRenderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(pListView), pColumn); pScrollbar = gtk_scrolled_window_new(NULL, NULL); gtk_widget_show(pScrollbar); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pScrollbar), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(pScrollbar), GTK_SHADOW_IN); gtk_container_add(GTK_CONTAINER(pScrollbar), pListView); // Onglet GtkWidget *pHBoxOnglet; GtkWidget *pButtonOnglet; GtkWidget *pTabLabel; pHBoxOnglet = gtk_hbox_new(FALSE, 0); gtk_widget_show(pHBoxOnglet); char *text=g_convert(name, -1, "UTF-8", "ISO-8859-1", NULL, NULL, NULL); pTabLabel = gtk_label_new(text); gtk_widget_show(pTabLabel); g_free(text); pButtonOnglet = gtk_button_new_with_label(" x "); gtk_widget_show(pButtonOnglet); gtk_button_set_relief (GTK_BUTTON (pButtonOnglet), GTK_RELIEF_NONE); if(strcmp(name, "Main") == 0) object = pButtonOnglet; g_signal_connect(G_OBJECT(pButtonOnglet), "clicked", G_CALLBACK(OnClicked), (gpointer*)notebook); gtk_box_pack_start(GTK_BOX (pHBoxOnglet), pTabLabel, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX (pHBoxOnglet), pButtonOnglet, FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX (pHBox), pScrolled, TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(pHBox), pScrollbar, FALSE, FALSE, 0); gtk_notebook_append_page(GTK_NOTEBOOK(notebook), pHBox, pHBoxOnglet); } } int main(int argc, char *argv[]) { GtkWidget *window; GError *error = NULL; WidgetNoteBook yes_args; /* init threads */ g_thread_init(NULL); gdk_threads_init(); /* init gtk */ gtk_init(&argc, &argv); /* create a window */ window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_default_size(GTK_WINDOW(window), 320, 200); g_signal_connect(window, "destroy", G_CALLBACK(destroy), NULL); gtk_container_set_border_width(GTK_CONTAINER (window), 0); /* create a label */ GtkWidget *pNotebook; pNotebook = gtk_notebook_new(); gtk_notebook_set_tab_pos(GTK_NOTEBOOK(pNotebook), GTK_POS_TOP); gtk_notebook_set_scrollable(GTK_NOTEBOOK(pNotebook), TRUE); gtk_container_add(GTK_CONTAINER(window), pNotebook); addPage(pNotebook, "Main"); /* show everything */ gtk_widget_show(pNotebook); gtk_widget_show(window); /* create the threads */ yes_args.noteBook = pNotebook; if (!g_thread_create(argument_thread, &yes_args, FALSE, &error)) { g_printerr ("Failed to create YES thread: %s\n", error->message); return 1; } //gtk_widget_show_all(window); /* enter the GTK main loop */ gdk_threads_enter(); gtk_main(); gdk_threads_leave(); return 0; } Other information:
One can't call GTK+ functions from multiple threads in Windows. Sorry.
*** This bug has been marked as a duplicate of 60620 ***