【问题标题】:Python GTK+ 3 Safe ThreadingPython GTK+ 3 安全线程
【发布时间】: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() 的存在。

【问题讨论】:

    标签: python multithreading gtk3


    【解决方案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,如何安全地使用这些锁。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-17
      • 2011-08-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多