基本上我有一个启动新线程的程序,然后尝试在这个新线程中执行操作。但是,新线程似乎陷入困境,直到主线程到达程序结束。
这是我遇到的问题的一个工作示例。似乎gtk.main()必须存在才能发生此问题。如果我使用类似输入()的东西,则不会出现问题。
import threading,sys
class MyThread(threading.Thread):
def run(self):
import time
print('before')
time.sleep(3)
print('after')
MyThread().start()
from gi.repository import Gtk as gtk
class My_window:
def __init__(self):
self.window = gtk.Window()
self.window.connect("delete_event", gtk.main_quit)
self.button = gtk.Button("Hello World")
self.window.add(self.button)
self.button.show()
self.window.show()
My_window()
gtk.main()
应该发生什么:出现窗口,出现之前的单词,3秒后出现单词
真正发生的事情:出现窗口,出现之前的单词,然后没有任何反应。当您关闭窗口时,会出现单词after。 (好像以某种方式到达程序的末尾会使之前被冻结的所有正在运行的线程再次运行)
我尝试过的事情:
将time.sleep替换为其他函数,如终端命令或繁忙循环。我得到了相同的结果
我尝试在没有窗口和其他额外内容的情况下重新创建问题,但不能。所以我不知道这个问题在哪里,所以我提供了所有背景信息。
我尝试使用sys.stdout.flush()来确保文本实际显示在命令行中。它是。
有没有人对这个问题有什么建议?
我正在使用python 3(和gtk用于窗口),并希望我的程序兼容所有主要的操作系统
修改
我尝试在gtk.main()之前放置一个pring('starting')。输出显示之前然后开始。我认为调用gtk.main冻结所有线程,当gtk.main结束时,线程恢复。
编辑2: 从来没有想过,在我的orriginal程序中,线程是在gtk.main运行时创建的,但gtk.main中仍然可能存在冻结线程的东西,每隔一段时间就会调用一次。
答案 0 :(得分:2)
我设法重现了这一点,并且花了很多时间试图解决它失败的原因,直到我遇到this FAQ entry,其中建议放...... [/ p>
import gobject
gobject.threads_init()
...代码顶部,似乎可以解决问题。
我的猜测是,在调用gtk.main()
之后,GTK继续使用Python的Global Interpreter Lock,这对于默认行为有点顽皮,但至少有一种方法可以阻止它。
请注意,后台线程无法直接操作GTK对象,因此您必须让它们将消息传递给主线程来代替。
答案 1 :(得分:0)
如果你是你创建的线程对象,你应该在启动它之前使用th.setDaemon(1),否则主线程将不会退出而没有你先开始退出的线程。