PyGTK:带线程的gobject.idle_add()和timeout_add()

时间:2013-11-29 18:36:40

标签: multithreading user-interface thread-safety gtk pygtk

是否有任何明确的文档说明idle_add()/ timeout_add()和/或它们安装的实际回调是否需要锁(任何类型)?

def work(*args):
  # (1) gtk.gdk.threads_enter() #needed?
  self.ui.change_some_label()
  # (2) gtk.gdk.threads_leave() #?

# (3) gtk.gdk.threads_enter()   #?
gobject.idle_add (work)
# (4) gtk.gdk.threads_leave()   #?

def main():
  gtk.gdk.threads_init()
  #...

是否需要1 + 2和/或3 + 4?对于哪个pygtk版本 这适用吗?我的目标是单独2.12(在嵌入式 平台)和2.24(在桌面上)。线程是由于gstreamer。

对于底层的C函数g_idle_add(),g_timeout_add()我找到了一个gtk-app-devel discussion表示

  

如果你已经调用了gdk_threads_init,那么就是空闲和超时处理程序   将运行而不用 gdk线程锁定,您将不得不添加   gdk_threads_enter /如果你正在做gui的话就自己打电话。

...虽然这是从2004年开始的。我发现很难为GTK + -2或PyGTK找到明确的特定文档。

关于SO的许多答案支持通过idle_add调度GUI工作,没有任何锁/关键部分(例如GUI not updated from another thread when using PyGtk

1 个答案:

答案 0 :(得分:4)

调用g_idle_add()g_timeout_add()不需要锁定:它们是线程安全的操作,并保证在当前正在旋转主循环的GMainContext中调用回调。 / p>

您链接的文档说回调需要获取GDK主锁;回调由GLib调用,但锁定由GDK提供,因此您需要显式获取它以避免线程在回调发射期间中断。

因此,C API提供了gdk_threads_add_idle()gdk_threads_add_timeout()函数(以及它们的full()变体),它们保证在保持GDK锁的情况下调用您的回调。 PyGTK不会包装这些函数,因为它还需要保存Python解释器锁;这意味着您需要记住在回调中自己致电gdk_threads_enter() / gdk_threads_leave()