【问题标题】:Threading not working with pygtk and always hangs线程不适用于 pygtk 并且总是挂起
【发布时间】:2012-10-25 19:25:43
【问题描述】:

这是我的问题的一个小实现。当我单击“按下”按钮时,它会挂起,有时不会。如何克服这个问题? 这是我的代码。

要安装 Sane "sudo apt-get install python-imaging-sane"

import gtk
import gtk.glade
import threading
import os
import sane
gtk.gdk.threads_init()
class process(threading.Thread):
    def __init__(self,main_object):
        self.main_object = main_object
        threading.Thread.__init__(self)

    def run(self):
        sane_version = sane.init()
        sane_devices = sane.get_devices()
        gtk.threads_enter()
        self.main_object.pb.set_fraction(self.main_object.value)
        gtk.threads_leave()
        self.main_object.value = self.main_object.value + .1


class main():
    def __init__(self):
        #GUI
        window = gtk.Window()
        window.set_default_size(200,200)
        vbox = gtk.VBox(False,0)

        self.pb = gtk.ProgressBar()
        button = gtk.Button("Press me ")
        button.connect("clicked",self.fun_to_call)
        vbox.pack_end(self.pb)
        vbox.pack_end(button)
        button.show()
        self.pb.show()
        vbox.show()
        window.add(vbox)

        self.value = .1
        window.show()

    def fun_to_call(self,data=None):
        pro = process(self)
        pro.start()


main()
gtk.main()

【问题讨论】:

  • 你知道 Sane 绑定是否是线程安全的吗?如果他们不为任何长时间运行的操作跳 Py_BEGIN_ALLOW_THREADS/Py_END_ALLOW_THREADS 跳舞,那么他们将阻止 Python 代码在其他线程中执行。

标签: python multithreading user-interface pygtk


【解决方案1】:

看着PyGTK FAQ on the subject,好像少了一步; (虽然整个常见问题解答条目很有趣)

...你必须用 gtk.threads_enter()/gtk.threads_leave() 包裹你的主循环,像这样:

gtk.threads_enter()
gtk.main()
gtk.threads_leave()

他们也有一些建议如何使用finally 来确保gtk.threads_leave() 始终运行,即使代码抛出异常也是如此。

请注意,尽管使用这种 GUI 线程不一定是可移植的,但某些操作系统可能会在非主线程运行 GUI 操作时遇到问题,即使锁定正确。

【讨论】:

    【解决方案2】:

    标准python实现(“cpython”)的内部不是线程安全的。

    所以使用锁(Global Interpreter Lock)来确保一次只运行一个 python 线程。这个锁被释放,例如当一个正在运行的线程进行 I/O 时。但是如果锁没有释放,其他线程就没有机会运行。

    我怀疑这是问题的根源。这取决于健全绑定的实现。

    您可以尝试使用multiprocessing 模块而不是threading。多处理为长时间运行的任务启动了一个完全不同的进程,因此它不受 GIL 的约束。但是您必须使用multiprocessing 提供的设施,如QueuePipe 在进程之间交换信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多