Python GTK + 3安全线程

jpc*_*cgt 4 python multithreading gtk3

那么我应该在我的程序开始时运行什么来使其成为线程安全的(或者我在某些地方读过的线程感知):

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()
Run Code Online (Sandbox Code Playgroud)

然后,我应该在我的线程中做什么?某种锁?使用Python的线程库是安全的还是我应该在GLib,GObject或Gdk中使用某些东西?我知道那里有很多问题/答案/例子,但它们都相互矛盾,不是Gtk + 3,不适合Python,或者只是不完整,甚至我认为是Python GI的正式文档(http ://lazka.github.io/pgi-docs/)甚至没有提到GObject.threads_init()和Gdk.threads_init()的存在.

小智 14

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

..但是,Gdk.threads_init()已被弃用,我建议:

  • 不要打电话给Gdk.threads_init,Gdk.threads_enter /离开
  • 使用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.

关于其他libs:

  • 一些GI模块可以在其他线程中发出某些信号/回调(例如GStreamer中的GstPlayBin ::即将完成的信号); 即使您根本不在代码中使用Python线程.不能直接在它们中调用Gdk/Gtk代码,如果需要也可以在那里使用idle_add.
  • GLib/GStreamer的许多部分都是线程安全的,可以从其他线程调用.

tl; dr:只有GObject.threads_init(),在线程中使用GLib.idle_add将所有Gtk/Gdk代码推送到主线程