如何在关闭Tkinter窗口时立即终止工作线程?
解决Tkinter窗口关闭时立即停止工作线程的问题
问题分析
你的代码存在两个核心问题:
- Tkinter线程安全违规:工作线程直接创建并操作
Progressbar组件,但Tkinter所有GUI操作必须在主线程执行,这种跨线程操作本身就有风险。 - 线程未被安全终止:窗口关闭后,工作线程仍阻塞在
time.sleep(10)中,后续尝试操作已销毁的ROOT对象,触发RuntimeError。
解决方案
我们通过**线程事件(Event)**实现安全终止线程,同时将所有GUI操作移回主线程,严格遵循Tkinter的线程安全规则。
修改后的代码如下:
import tkinter as tk from tkinter import ttk import threading import time def worker(event_ready, stop_event): event_ready.wait() # 循环检查停止信号,避免长时间阻塞 while not stop_event.is_set(): # 委托主线程启动进度条 ROOT.after(0, progress_bar.start) # 用可中断的等待代替time.sleep,响应停止信号 if stop_event.wait(10): break # 委托主线程停止进度条 ROOT.after(0, progress_bar.stop) # 窗口关闭时的处理逻辑 def on_closing(): # 触发停止事件,通知工作线程退出 stop_event.set() # 等待工作线程安全结束 worker_thread.join() # 销毁窗口 ROOT.destroy() event_ready = threading.Event() stop_event = threading.Event() # 主线程初始化GUI组件 ROOT = tk.Tk() ROOT.geometry('300x120') ROOT.title('TEST') ROOT.grid() progress_bar = ttk.Progressbar(ROOT, orient='horizontal', mode='indeterminate', length=280) progress_bar.grid(column=0, row=0, columnspan=2, padx=10, pady=20) # 绑定窗口关闭事件 ROOT.protocol("WM_DELETE_WINDOW", on_closing) # 启动工作线程 worker_thread = threading.Thread(target=worker, args=(event_ready, stop_event,)) worker_thread.start() event_ready.set() ROOT.mainloop()
关键改动说明
- 新增
stop_event事件:用于向工作线程传递终止信号,用stop_event.wait(10)替代time.sleep(10),让线程能在等待过程中响应停止指令,无需等到睡眠结束。 - GUI操作主线程化:通过
ROOT.after(0, ...)将进度条的启动、停止操作委托给主线程执行,彻底避免跨线程操作GUI的风险。 - 窗口关闭绑定处理函数:通过
ROOT.protocol绑定自定义关闭逻辑,确保在窗口销毁前先停止工作线程,等待线程安全退出后再销毁窗口。
内容的提问来源于stack exchange,提问作者Divy X
相关产品推荐
相关产品推荐

