3

基本上我有一个程序启动一个新线程,然后尝试在这个新线程中做一些事情。但是,新线程似乎卡住了,直到主线程到达程序末尾。

这是我遇到的问题的一个工作示例。似乎 gtk.main() 必须存在才能发生此问题。如果我改用 input() 之类的东西,则不会出现问题。

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() 之前放置一个 print('starting')。输出显示之前然后开始然后之后。我在想调用 gtk.main 会冻结所有线程,当 gtk.main 结束时,线程会恢复。

编辑 2: 没关系,在我的原始程序中,线程是在 gtk.main 运行时创建的,但 gtk.main 中仍然可能存在冻结线程的东西,每隔一段时间就会调用一次。

4

2 回答 2

3

我设法重现了这一点,并花了很长时间试图找出它失败的原因,直到我遇到这个常见问题解答条目,它建议把......

import gobject
gobject.threads_init()

...在代码的顶部,这似乎解决了问题。

我的猜测是,在调用 之后gtk.main(),GTK 会保留 Python 的Global Interpreter Lock,这对于默认行为来说有点顽皮,但至少有一种方法可以防止它。

请注意,后台线程无法直接操作 GTK 对象,因此您必须让它们将消息传递给主线程才能执行此操作。

于 2013-05-18T17:27:26.163 回答
0

如果 th 是你创建的线程对象,你应该在启动它之前 th.setDaemon(1) ,否则如果你启动的线程先退出,主线程就不会退出。

于 2013-05-18T16:39:35.213 回答