Dbus/GLib 主循环,后台线程

Posted

技术标签:

【中文标题】Dbus/GLib 主循环,后台线程【英文标题】:Dbus/GLib Main Loop, Background Thread 【发布时间】:2011-12-06 03:54:46 【问题描述】:

我一般从 DBus 和事件驱动编程开始。我正在尝试创建的服务实际上由三部分组成,但其中两部分是真正的“服务器”。

1) 实际的 DBus 服务器通过 HTTPS 与远程网站通信,管理会话,并向客户端传送信息。

2) 服务的另一部分每 2 分钟调用一次保持活动页面,以使会话在外部网站上保持活动状态

3) 客户端调用服务以从服务中检索信息。

我找到了一些简单的示例程序。我正在尝试使它们适应原型#1 和#2。而不是为两者构建单独的程序。我以为我可以在一个两个线程的进程中运行它们。

我看到的问题是我在保持活动线程中调用 time.sleep(X)。线程进入睡眠状态,但永远不会醒来。我认为 GIL 不是由 GLib 主循环释放的。

这是我的线程代码:

class Keepalive(threading.Thread):
  def __init__(self, interval=60):
    super(Keepalive, self).__init__()
    self.interval = interval
    bus = dbus.SessionBus()
    self.remote = bus.get_object("com.example.SampleService", "/SomeObject")

  def run(self):
    while True:
        print('sleep %i' % self.interval)
        time.sleep(self.interval)
        print('sleep done')
        reply_status = self.remote.keepalive()
        if reply_status:
            print('Keepalive: Success')
        else:
            print('Keepalive: Failure')

从打印语句中,我知道睡眠开始了,但我从未看到“睡眠完成”。

这里是主要代码:

if __name__ == '__main__':
try:
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    session_bus = dbus.SessionBus()
    name = dbus.service.BusName("com.example.SampleService", session_bus)
    object = SomeObject(session_bus, '/SomeObject')

    mainloop = gobject.MainLoop()

    ka = Keepalive(15)
    ka.start()
    print('Begin main loop')
    mainloop.run()
except Exception as e:
    print(e)
finally:
    ka.join()

其他一些观察:

我看到“开始主循环”消息,所以我知道它正在获得控制权。然后,我看到“sleep %i”,然后什么也没有。

如果我 ^C,那么我看到“sleep done”。大约 20 秒后,我从 self.run() 收到远程应用程序没有响应的异常:

DBusException:org.freedesktop.DBus.Error.NoReply:没有收到回复。可能的原因包括:远程应用未发送回复、消息总线安全策略阻止回复、回复超时或网络连接中断。

在服务器中运行我的保持活动代码的最佳方式是什么?

谢谢,

【问题讨论】:

【参考方案1】:

在使用gobject 时,您必须通过调用gobject.threads_init() 显式启用多线程。有关背景信息,请参阅PyGTK FAQ。

除此之外,就您所描述的目的而言,超时似乎更合适。使用如下:

# Enable timer
self.timer = gobject.timeout_add(time_in_ms, self.remote.keepalive)
# Disable timer
gobject.source_remove(self.timer)

这会每隔time_in_ms (milli) 秒调用一次keepalive 函数。更多详情,请再次访问PyGTK reference。

【讨论】:

Jro,感谢您的建议。我是新手,真的不明白 dbus/glib/gtk/gobject 之间的关系。 tomeout_add() 正是我想要的。

以上是关于Dbus/GLib 主循环,后台线程的主要内容,如果未能解决你的问题,请参考以下文章

什么是后台线程、前台线程和主线程?

如何防止主线程ios杀死后台线程

没有主线程可以存在后台线程吗?

在后台线程执行硬任务,在主线程返回结果

无法从 iOS6 中的后台线程调用主线程上的代码

将 NSManagedObject(在主上下文中创建)从后台线程传递到主线程是不是安全?