一个线程中的GLib GMainContext?

我搜索了堆栈溢出来找到与我的问题相关的答案。 但我没有找到任何答案。

我有一个主线程(我的main()函数),它启动一个线程。 新线程运行GMainLoop。 在我的主要function中,我通过在某些文件描述符上调用g_io_watch来继续添加源代码。 但是,如果发送了事件,我会收到垃圾数据。

以下是我正在尝试的代码的一小部分:

 GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { loop = g_main_loop_new(NULL, FALSE); g_thread_new(NULL, event_loop_thread, NULL); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); while (true); // I will close file descriptor return 0; } 

但是,如果我尝试此代码,那么一切都按预期工作:

 GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { loop = g_main_loop_new(NULL, FALSE); g_thread_new(NULL, event_loop_thread, NULL); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { // init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); loop = g_main_loop_new(NULL, FALSE); g_main_loop_run(loop); g_main_loop_unref(loop); while (true); // I will close file descriptor return 0; } 

编辑:

我已经尝试将主线程的默认GMainContext传递给新创建的线程。 看一看。 告诉我,我的方法是否正确。

 GMainLoop *loop; gpointer event_loop_thread(gpointer arg) { GMainContext *context = (GMainContext *)arg; loop = g_main_loop_new(context, FALSE); g_main_context_push_thread_default(context); g_main_loop_run(loop); g_main_loop_unref(loop); return NULL; } int init() { g_thread_new(NULL, event_loop_thread, (gpointer)g_main_context_default()); return 0; } gboolean __hci_service(GIOChannel *source, GIOCondition condition, gpointer data) { // Doing something return FALSE; } int main() { init(); int _adapter_id = hci_devid("hci0"); int hci_dev = hci_open_dev(_adapter_id); GIOChannel *p_hci_io = g_io_channel_unix_new(dev_id); GIOCondition cond = (GIOCondition)(G_IO_IN); g_io_add_watch(p_hci_io, cond, __hci_service, NULL); //loop = g_main_loop_new(NULL, FALSE); //g_main_loop_run(loop); //g_main_loop_unref(loop); while (true); // I will close file descriptor return 0; } 

如果要从线程运行主循环,则需要使用GMainContext 。 从Glib的主循环文档 :

为了允许在不同的线程中处理多个独立的源集,每个源与GMainContext相关联。 GMainContext只能在单个线程中运行,但可以将源添加到其中并从其他线程中删除。

使用g_main_loop_new(NULL, FALSE);创建主循环时g_main_loop_new(NULL, FALSE); 虽然没有指定任何GMainContext很方便,但是如果你想在不同的线程中运行循环,你需要传递一个你想要你的循环的GMainContext。 您可以使用g_main_context_new()创建GMainContext并将其传递给g_main_loop_new() ,或使用g_main_context_get_thread_default()获取正在运行的线程的默认主要上下文。

g_io_add_watch()是该函数的另一个方便版本

使用默认优先级将GIOChannel添加到默认主循环上下文中。

遗憾的是,没有g_io_add_watch()变量函数来指定主上下文,您必须从GIOChannel手动创建GSourcep_hci_io ,并通过g_source_attach()附加到您的上下文。 请注意, g_io_add_watch_full()也适用于默认主上下文。

您的第二个代码工作的原因是您在主线程中创建了主循环,其中包含您的源代码。