Multithreading PyGTK、线程和可访问性-应用程序挂起

Multithreading PyGTK、线程和可访问性-应用程序挂起,multithreading,gtk,accessibility,pygtk,Multithreading,Gtk,Accessibility,Pygtk,我使用PyGTK创建了一些应用程序,并认为它们还可以,直到我在Ubuntu上支持可访问性的GNOME和Debian上支持Openbox的环境中执行它们。我发现它们会挂起,更令人沮丧的是,它们会导致AT-SPI应用程序挂起 我已经创建了一个包含PyGTK和线程的所有变体的: primarythread前缀表示gtk.main在主线程内工作 一个首先由Python执行, secondarythread前缀表示gtk.main在secondary thread内工作, 多处理前缀表示导入和gtk.ma

我使用PyGTK创建了一些应用程序,并认为它们还可以,直到我在Ubuntu上支持可访问性的GNOME和Debian上支持Openbox的环境中执行它们。我发现它们会挂起,更令人沮丧的是,它们会导致AT-SPI应用程序挂起

我已经创建了一个包含PyGTK和线程的所有变体的:

primarythread前缀表示gtk.main在主线程内工作 一个首先由Python执行, secondarythread前缀表示gtk.main在secondary thread内工作, 多处理前缀表示导入和gtk.main在另一个进程中执行

gobject后缀表示仅使用了gobject.threads_init

gtkgdk后缀表示已使用gobject和gtk.gdk.threads_init, 导入后缀表示导入gtk在新线程内执行。 showApps.py是使用AT-SPI列出启用了可访问性的应用程序的示例

我在下表中也在文件中总结了测试:

当AT-SPI被标记为“挂起”时,它将在应用程序列表期间无条件挂起

PyGTK应用程序的挂起发生在通过窗口丢失和恢复焦点之后

测试表明,从第一个/主Python线程运行gtk.main时不会出现问题。但这并不能让我满意,因为我不喜欢将GUI作为应用程序的主要部分

我的问题是:

标记为secondarythread的程序中的代码有什么问题吗?还是GTK/GAIL/AT-SPI中的一个bug? 是否有禁止在第一个/主Python线程之外运行gtk.main的策略?
我知道的唯一策略是,任何时候只有一个线程可以访问GTK库

如果您希望GUI在自己的辅助线程中运行,那么您需要确保这是访问GTK的唯一线程,因为GTK不是线程安全的。这就是为什么在secondarythread情况下,只有从线程内导入GTK时,它才起作用。如果它是在线程外部加载的,那么从技术上讲,主线程在某种程度上也在使用它,两个线程可以同时尝试访问库。。primarythread案例之所以有效,是因为您使用GTK.gdk.threads\u enter和threads\u leave正确地锁定了对GTK库的访问。我认为您可以在secondarythreadgtkgdk_import.py中删除它们,这样就可以了,因为只有一个线程知道已经加载了GTK

现在,这是我的猜测,因为我对AT-SPI不太了解。由于您已经在secondarythread_gobject.py和secondarythread_gtkgdk.py中的两个独立线程中造成了争用条件,因此AT-SPI也可能会以某种方式受到此状态的影响

如果你真的希望你的GUI在一个辅助线程中,使用secondarythread_gtkgdk_import.py,可能会删除不必要的线程。我建议您将GUI作为主线程,并在子线程中启动所有后台进程

比较以下两个示例:

import threading
import time

class mythread(threading.Thread):
    def __init__(self):
        super(mythread, self).__init__()

    def run(self):
        print time.ctime()


t = mythread()
t.run()
print time.ctime()

$ python2 test.py
Mon Aug 15 23:12:41 2011
Mon Aug 15 23:12:41 2011
在第一种情况下,时间从主线程导入,然后生成一个子进程。子进程也可以访问时间,因此时间会打印两次。在第二种情况下,时间被导入子线程。但是,父线程没有看到这一点,因此对time.ctime的第二次调用失败


当您从子线程加载GTK时,父线程不知道它,因此当两个线程试图访问GTK库引用GDK文档时,您永远不会遇到问题:也就是说,在任何给定时间只有一个线程可以使用GTK+

对不起,但你写的东西不合逻辑,而且据说部分是不正确的。首先,我认为需要对同时使用某物下定义。我认为,当我们同时谈论使用资源时,我们谈论的是阅读和编写共享资源。我不认为将两个线程中的某个东西同时声明为使用。如果存在一个假设,即导入模块将模块锁定到一个线程,或者Python线程与GTK线程完全分离,则应该在文档中提到。首先,您写到问题在于两个线程正在使用库。您提到的进入和离开功能适用于此特定场合。要使用它们,我必须导入GTK。我也不知道你在哪里注意到了比赛情况。从外部到GTK的通信应仅通过GTK_main进行。当它执行时,主线程已经完成了与GTK的交互。关于你的第一条评论,我不是在编造:关于你的第二条评论,我希望我添加的示例有助于澄清我的意思。但是你只是引用了句子的一部分。这完全改变了那一段的含义。完整段落:>>>GTK+是线程感知的,但不是 线程安全-它提供了一个由gdk_threads_enter/gdk_threads_leave控制的全局锁,用于保护GTK+的所有使用。也就是说,在任何给定时间只有一个线程可以使用GTK+。
import threading
import time

class mythread(threading.Thread):
    def __init__(self):
        super(mythread, self).__init__()

    def run(self):
        print time.ctime()


t = mythread()
t.run()
print time.ctime()

$ python2 test.py
Mon Aug 15 23:12:41 2011
Mon Aug 15 23:12:41 2011
import threading

class mythread(threading.Thread):
    def __init__(self):
        super(mythread, self).__init__()

    def run(self):
        import time
        print time.ctime()


t = mythread()
t.run()
print time.ctime()

$ python2 test.py
Mon Aug 15 23:12:46 2011
Traceback (most recent call last):
  File "test.py", line 15, in <module>
    print time.ctime()
NameError: name 'time' is not defined