You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在关闭Tkinter窗口时立即终止工作线程?

解决Tkinter窗口关闭时立即停止工作线程的问题

问题分析

你的代码存在两个核心问题:

  1. Tkinter线程安全违规:工作线程直接创建并操作Progressbar组件,但Tkinter所有GUI操作必须在主线程执行,这种跨线程操作本身就有风险。
  2. 线程未被安全终止:窗口关闭后,工作线程仍阻塞在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 04:32:40