繁体   English   中英

Python GTK + 3安全线程

[英]Python GTK+ 3 Safe Threading

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

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()已被弃用 ,我建议:

  • 不要打电话给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代码推送到主线程

如果有人要在多线程代码中使用GTK,那么必须阅读文档。 https://wiki.gnome.org/Attic/GdkLock

这个文件真的帮助我理解了如何在一个进程中从C运行GTK以及从python运行GTK(通过PyGTK只是在python中导入gtk)。 虽然XInitThreads()可以在Linux中避免使用GDK Lock,但它不是Windows的解决方案。 g_idle_add()g_timeout_add()这样的函数是防止GUI压缩的通用解决方案。 但是gdk_threads_enter()和gdk_thread_leave()还没有完全没用。 该文档阐明了如果有人想要从不同的线程或自定义事件处理程序或g_idle_add()回调更新GUI,如何安全地使用这些锁。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM