Tôi đang xây dựng khá đơn giản C application bằng GTK, nhưng phải thực hiện một số IO chặn sẽ kích hoạt cập nhật cho GUI. Để làm được điều này, tôi bắt đầu một pthread
đúng mới trước khi gtk_main()
như vậy:Vấn đề về luồng với 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();
Khi pthread
đọc một số dữ liệu, nó cập nhật GUI như vậy:
g_main_context_invoke(mainc, set_icon, param);
đâu set_icon
là
gboolean set_icon(gpointer data)
{
char *p = (char*)data;
gtk_status_icon_set_from_icon_name(icon, p);
return FALSE;
}
Điều này tất cả hoạt động hầu hết thời gian, nhưng hiện tại tôi nhận được thông báo lỗi tò mò này:
[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.
Tôi nghĩ rằng toàn bộ điểm sử dụng g_main_context_invoke
là để tránh các vấn đề với chủ đề? Làm một chút Googling, tôi đi qua gdk_threads_init
, gdk_threads_enter
và bạn bè, nhưng tất cả chúng dường như không được chấp nhận? Tôi biết tài liệu GTK nói rằng tất cả các cập nhật GUI nên được thực hiện trên luồng chính, nhưng điều này không kết hợp tốt với việc chặn IO, và tôi không muốn xây dựng một số cơ chế giao tiếp phức tạp giữa các luồng.
Và vì vậy, câu hỏi của tôi là, tôi nên xử lý chính xác điều này như thế nào?
EDIT: Mã đầy đủ có thể được nhìn thấy here EDIT2: Như một bản cập nhật dựa trên câu trả lời @ ptomato, tôi đã chuyển sang GThread
s và sử dụng gdk_threads_add_idle()
như đã thấy trong this cam kết, nhưng vấn đề vẫn còn hiện diện.
Bạn có sẵn một số mã không, tôi đã sử dụng gtk + trong một thời gian và _never_ đã gặp vấn đề này .. – drahnr
Toàn bộ mã có sẵn tại [GitHub] (https://github.com/jonhoo/mktrayicon) như được liên kết trong bài đăng. –
Ah, nhớ lời cảm ơn đó! – drahnr