根据“正确终止GLib主回路”;“退出”;C中的旗帜

根据“正确终止GLib主回路”;“退出”;C中的旗帜,c,glib,C,Glib,我意识到这可能是一个新手油嘴滑舌的问题,但我很难找到解决下面问题的代码示例。所以,在我走错太远之前,我想听听你的建议 我的代码侦听D-Bus消息。一条D-Bus消息是“退出”消息,用于指示主回路关闭。如果主循环中没有其他任务,一个简单的解决方案是在下面的代码中调用g\u main\u loop\u run(),并在收到“quit”消息时让D-Bus消息处理代码(此处未显示)执行g\u main\u loop\u quit() 然而,我更喜欢由主循环做出退出的决定,主循环除了监听D-Bus消息之外

我意识到这可能是一个新手油嘴滑舌的问题,但我很难找到解决下面问题的代码示例。所以,在我走错太远之前,我想听听你的建议

我的代码侦听D-Bus消息。一条D-Bus消息是“退出”消息,用于指示主回路关闭。如果主循环中没有其他任务,一个简单的解决方案是在下面的代码中调用
g\u main\u loop\u run()
,并在收到“quit”消息时让D-Bus消息处理代码(此处未显示)执行
g\u main\u loop\u quit()

然而,我更喜欢由主循环做出退出的决定,主循环除了监听D-Bus消息之外,还可以执行其他各种任务。以下代码在设置工作的D-Bus服务器后按预期执行此操作:

GMainLoop *glib_mainloop = g_main_loop_new( NULL, false );
/* Set up the D-Bus connection to work in the GLib event loop. */
dbus_connection_setup_with_g_main( dbus_connection, NULL );

/* Run the GLib event loop. */
GMainContext *glib_context = g_main_context_default( );
while( quit_indicator == false )
{
    g_main_context_iteration( glib_context, /*allow blocking=*/false );
    /* Do a variety of other tasks. */
}

g_main_loop_quit( glib_mainloop );
注意:以上是用来说明我的问题的最少代码,我知道主循环中的“其他任务”可以通过线程、
GSource
s或其他方式更好地处理。例如,如果按原样使用上述代码,则会出现明显的忙等待或计时问题


我的问题是:上面的代码示例是实现我想要的功能的正确方法,还是有一种更“真实”的油嘴滑舌的方法呢?

您的方法基本上是正确的。很多例子都说使用
g\u main\u loop\u run()
g\u main\u loop\u quit()
来控制主上下文,但是在执行时手动迭代主上下文更清晰

应该对代码进行的一个更改是告诉
g\u main\u context\u iteration()
允许阻塞,否则您的主循环本质上是一个繁忙的循环,并且您的进程在等待I/O时不会休眠。如果手动迭代
gmainotext
,您也根本不需要使用
GMainLoop

另一个必要的更改是调用
g\u main\u context\u wakeup()
,在更改终止条件的值时,从
g\u main\u context\u iteration()
中的阻塞中唤醒主上下文

第三,使用
g\u main\u loop\u new()
/
g\u main\u loop\u quit()
创建和退出
GMainLoop
在代码中没有任何作用,因为
GMainLoop
永远不会与
g\u main\u loop\u run()
一起运行。放下那些电话

以下是更新版本:

GMainContext *context = g_main_context_default ();
gboolean quit = FALSE;

/* Set up the D-Bus connection to work in the GLib event loop. */
dbus_connection_setup_with_g_main (dbus_connection, context);

/* Run the GLib event loop. */
while (!quit)
  g_main_context_iteration (context, TRUE);

/* To exit the main loop (from a callback implementing your D-Bus Quit() function): */
quit = TRUE;
g_main_context_wakeup (NULL  /* global default main context */);
其他几点:

  • 正如您所指出的,注释中的“其他任务”应该在主上下文的回调中执行
  • 使用GDBus,而不是dbus glib(不推荐使用且未维护)。我已经写了为什么,以及如何选择D-Bus绑定
  • 如果要在新线程(而不是主线程)中执行此操作,则应使用新的
    GMainContext
    g_autoptr(GMainContext)context=g_main_context_new();g\u主线程\u上下文\u推送线程\u默认值(上下文)。您不应该在多个线程之间共享
    GMainContext
    。虽然这样做是安全的,但它并没有表现出来

这里有一个MPL许可的主循环示例,它是使用这些技术在一个基于GLib的现代守护程序中实现的:

这似乎更适合Wonderful!我肯定错过了
g\u main\u context\u wakeup()
。我知道dbus glib已经过时了,但到目前为止我还没有找到GDBus的工作示例。GIO测试中有大量的GDBus示例。其中一些是从文档中链接到的,但其他的也很有用。在这些文件中寻找“示例”:真的,真的停止使用dbusglib。它不受支持,而且很难与其他东西集成。我最终按照您的建议迁移到了GDBus。我已经在开发主机上安装并运行了dbusglib,但使用稍微不同的Linux发行版的部署目标设备似乎包含了一个有缺陷的dbusglib版本。幸运的是,迁移到GDBus只花了几个小时,从一开始就不了解GDBus到将其与其余代码集成。很高兴听到这个消息!