因此,我应该在程序的开头运行什么以使其具有线程安全性(或在某些地方已读懂线程安全性):

from gi.repository import Gtk, Gdk, GLib, GObject
import threading

GLib.threads_init()     # ?
GObject.threads_init()  # YES!
Gdk.threads_init()      # ?

my_app()

def my_threaded_func():
   Glib.idle_add(lambda: some_gui_action())
   Glib.timeout_add(300, lambda: some_gui_action())

t = threading.Thread(target=my_thread_func)
t.daemon = True
t.start()

Gtk.main()

然后,我应该在线程中做什么?某种锁?使用Python的线程库是否安全?还是应该在GLib,GObject或Gdk中使用某些内容?我知道那里有很多问题/答案/示例,但是它们彼此矛盾,不是针对Gtk + 3,不是针对Python,或者仅仅是不完整,甚至我认为是Python GI的官方文档(http://lazka.github.io/pgi-docs/ )甚至没有提到GObject.threads_init()和Gdk.threads_init()的存在。

最佳答案

https://wiki.gnome.org/Projects/PyGObject/Threading

..但是Gdk.threads_init() is deprecated,我建议:

  • 不在
  • 上调用Gdk.threads_init,Gdk.threads_enter/leave
  • 使用GLib.idle_add代替Gdk.threads_add_idle(或任何其他Gdk.threads_ *函数)
  • 使用GLib.idle/timeout_add
  • 将触摸Gdk/Gtk的东西推到主线程

    为什么?:
  • 不调用Gdk.threads_init表示将没有锁,如果您从不从另一个线程访问GDK则可以。
  • Gdk.threads_enter不执行任何操作,因为没有锁定。
  • 在这种情况下,
  • GLib.idle_add等于Gdk.threads_add_idle

  • 关于其他库:
  • 一些GI模块可以在其他线程中发出某些信号/回调(例如,在GStreamer中,GstPlayBin::about-to-finish信号);即使您根本不在代码中使用Python线程。不能直接在其中调用Gdk/Gtk代码,如果需要,也可以在其中使用idle_add。
  • GLib/GStreamer的许多部分都是线程安全的,可以从其他线程中调用。

  • tl; dr:线程中的仅GObject.threads_init(),使用将所有Gtk/Gdk代码插入主线程GLib.idle_add

    关于Python GTK + 3安全线程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21150914/

    10-08 21:51