Python GTK+ 3 安全线程
Posted
技术标签:
【中文标题】Python GTK+ 3 安全线程【英文标题】:Python GTK+ 3 Safe Threading 【发布时间】:2014-01-16 00:05:08 【问题描述】:那么我应该在我的程序开头运行什么以使其成为线程安全的(或者我在某些地方读到的线程感知):
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 的官方文档(@ 987654321@) 甚至没有提到 GObject.threads_init() 和 Gdk.threads_init() 的存在。
【问题讨论】:
【参考方案1】: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(),在线程中使用 GLib.idle_add 将所有 Gtk/Gdk 代码推送到主线程>
【讨论】:
您发布的链接使用Gdk.threads_init()
。你能链接到提到它已被弃用的来源吗?而且,你能解释为什么GLib.idle_add()
而不是Gdk.threads_add_idle()
吗?谢谢。
@lazca 我的应用程序没有崩溃,因为我实施了你的建议。为此非常感谢。还有两件事,使用GObject.threads_init()
而不是GLib.threads_init()
的理由是什么?毕竟我们使用GLib.add_idle()
来与主线程同步。我读到有人说最好使用并行进程而不是线程。你能评论一下吗?再次感谢。
(GLib.threads_init is GObject.threads_init) == True
。它只是一个别名.. 正如 PyGObject wiki 页面中所指出的,它与 GObject 或 GLib 无关,但由于历史原因仍然存在。您可以将其视为gi.threads_init()
。正如 wiki 页面上所指出的,自 3.10.2 以来不再需要它。【参考方案2】:
如果有人要在多线程代码中使用 GTK,这里是必须阅读的文档。 https://wiki.gnome.org/Attic/GdkLock
这份文档确实帮助我了解了如何在单个进程中从 C 和 python(通过 PyGTK 只是为了在 python 中导入 gtk)运行 GTK。尽管XInitThreads()
可以在 Linux 中避免 GDK 锁定,但它不是 Windows 的解决方案。 g_idle_add()
或 g_timeout_add()
等函数是防止 GUI 崩溃的通用解决方案。然而 gdk_threads_enter() 和 gdk_thread_leave() 还没有完全没用。该文档阐明了如果有人想从不同的线程或自定义事件处理程序或 g_idle_add()
回调更新 GUI,如何安全地使用这些锁。
【讨论】:
以上是关于Python GTK+ 3 安全线程的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Gtk.Application Gtk+3 Glade Python 更改/切换窗口?
在 Python-GTK3 中设置条目文本的 set_text 在哪里?