Buduję dość prosty C application używając GTK, ale muszę wykonać blokujące IO, które wyzwoli aktualizacje GUI. W tym celu, zaczynam nowy pthread
prawo przed gtk_main()
jako takie:Zgrywanie wątków z GTK
/* global variables */
GMainContext *mainc;
/* local variables */
FILE *fifo;
pthread_t reader;
/* main() */
mainc = g_main_context_default();
pthread_create(&reader, NULL, watch_fifo, argv[argc-1]);
gtk_main();
Gdy pthread
czyta jakieś dane, to aktualizuje GUI tak:
g_main_context_invoke(mainc, set_icon, param);
Gdzie set_icon
jest
gboolean set_icon(gpointer data)
{
char *p = (char*)data;
gtk_status_icon_set_from_icon_name(icon, p);
return FALSE;
}
To wszystko działa przez większość czasu, ale co jakiś czas pojawia się ciekawy komunikat o błędzie:
[xcb] Unknown sequence number while processing queue [xcb] Most likely this is a multi-threaded client and XInitThreads has not been called [xcb] Aborting, sorry about that. mktrayicon: xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
Myślałem, że jedynym celem korzystania z g_main_context_invoke
było unikanie problemów z wątkami? Trochę Googling, natknąłem gdk_threads_init
, gdk_threads_enter
i znajomych, ale wszystkie wydają się być przestarzałe? Wiem, że dokumentacja GTK mówi, że wszystkie GUI updaes powinny być wykonywane na głównym wątku, ale to nie łączy się dobrze z blokowaniem IO i wolałbym nie budować jakiegoś skomplikowanego mechanizmu komunikacji między wątkami.
Moje pytanie brzmi: w jaki sposób powinienem poradzić sobie z tym?
EDIT: Pełny kod widać here Edit2: jako aktualizacja na podstawie odpowiedzi @ ptomato za, ja przeniósł się do GThread
s i korzystania gdk_threads_add_idle()
jak widać w this popełnić, ale problem nadal występuje.
Czy masz dostęp do kodu, używam gtk + od jakiegoś czasu i _never_ natknąłem się na ten problem .. – drahnr
Cały kod jest dostępny na [GitHub] (https://github.com/jonhoo/mktrayicon) w powiązaniu z postem. –
Ah, przegapiłem to dzięki! – drahnr