【问题标题】:Python app with tkinter and threading error at closing关闭时带有 tkinter 和线程错误的 Python 应用程序
【发布时间】:2016-01-31 12:06:01
【问题描述】:

我正在为项目作业编写此软件,但在混合线程和 tkinter 时遇到问题。 以下部分大部分都按预期工作,但是当我关闭它时(在 Python shell 中启动它之后),windows 显示错误:“Python 停止工作”。

import threading
import time
import tkinter
import tkinter.ttk

class BTClient:
    def __init__(self, master):
        self.root = master
        self.root.bind("<Destroy>", self.on_destroy)

        self.t = threading.Thread(target=self.update)
        self.running = False

    def on_destroy(self, event):
        self.running = False

    def run_thread(self):
        self.running = True
        self.t.start()

    def update(self):
        while self.running:
            print("Update.")
            time.sleep(1)

def main(args):
    root = tkinter.Tk()
    client = BTClient(root)
    client.run_thread()
    root.mainloop()

if __name__ == "__main__":
    import sys
    main(sys.argv)

我该如何解决这个问题?它是由我使用的设计引起的吗?我应该改变它吗?

编辑 1: 当我删除 __init__ 中的 self.root 声明并仅使用 master 引用时,问题已解决,但我需要首先引用 GUI 对象构建 GUI 并从他们那里获取输入,所以我不知道如何解决这个问题。也许将对象作为参数传递给可能需要它们的所有东西?

【问题讨论】:

  • 你有没有尝试将线程封装在try/except中,看看错误信息是什么?我没有 tkinter 经验,但是在 wxpython 中出现了类似的问题,因为线程在关闭后尝试访问窗口。
  • 也许尝试将线程设置为守护进程 self.t.setDaemon(True)
  • 如果我将它设置为守护进程,线程会在主线程之后立即死亡,对吗?没有任何清理,我认为我需要这样做。
  • 是的。尝试将线程方法移到 BTClient 类之外,并添加 try/except 子句
  • 我假设当窗口关闭时,它会删除 BTClient 实例并且您的线程仍然需要该实例(self.running),因此它会抛出错误

标签: python multithreading tkinter


【解决方案1】:

如果没有看到您的实际代码,很难确切知道发生了什么,但我会让您的线程方法成为 BTClient 之外的函数,并将线程移到客户端之外,并在之后添加对 thread.join() 的调用mainloop 让您的线程在 GC 删除 BTClient 之前完成其清理

def update():
    import time
    while thread._keep_alive:
        time.sleep(1)
        print("thread running")

thread = threading.Thread(target=update)
thread._keep_alive = True
thread.start()

最后

thread._keep_alive = False
thread.join()

【讨论】:

  • 这段代码确实发生了错误,我认为不需要发布更多代码,对吧?
【解决方案2】:

所以我在root.mainloop() 之后添加了client.t.join() 行,这解决了问题,即使我真的不知道为什么。我认为这是因为当其他线程中仍有对它们的引用时,python 正在破坏 tkinter 对象,所以等待它们关闭解决了它。谢谢。

【讨论】:

  • 是的,这就是原因。 join 方法防止客户端被删除,直到线程完成。
猜你喜欢
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
  • 2014-06-06
  • 1970-01-01
  • 2013-01-24
  • 1970-01-01
  • 2021-04-12
  • 1970-01-01
相关资源
最近更新 更多