gpt4 book ai didi

python - Tcl_AsyncDelete 错误多线程 Python

转载 作者:行者123 更新时间:2023-11-28 21:53:09 26 4
gpt4 key购买 nike

听说Python的线程不好处理,和tkinter比较纠结。

我有以下问题。我有两个类,一个用于 GUI,另一个用于无限进程(我必须为两者都使用类)。首先,我启动 GUI 类,然后是无限进程类。我希望当您关闭 GUI 时,它也会结束无限进程并且程序结束。

代码的简化版本如下:

import time, threading
from tkinter import *
from tkinter import messagebox

class Interface(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.attrib1 = "Attrib from Interface class"

def run(self):
#Main Window
self.mainWindow = Tk()
self.mainWindow.geometry("200x200")
self.mainWindow.title("My GUI Title")
self.mainWindow.protocol("WM_DELETE_WINDOW", self.quit)
#Label
lbCommand = Label(self.mainWindow, text="Hello world", font=("Courier New", 16)).place(x=20, y=20)
#Start
self.mainWindow.mainloop()

#The Interface class contains methods that use attributes from itself and attributes from Process class.
def method1(self):
print(self.attrib1)
print(SecondThread.attrib2)

def quit(self):
if messagebox.askyesno('App','Are you sure you want to quit?'):
#In order to use quit function, mainWindow MUST BE an attribute of Interface.
self.mainWindow.destroy()
self.mainWindow.quit()

class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.attrib2 = "Attrib from Process class"

def run(self):
global finish
while not finish:
print("Proceso infinito")
#Inside the infinite process a method from Interface class is used.
GUI.method1()
time.sleep(3)

finish = False
#Starts the GUI
GUI = Interface()
GUI.start()
#Starts the infinity process
SecondThread = Process()
SecondThread.start()
#Waits until GUI is closed
GUI.join()
print("When GUI is closed this message appears")
#When GUI is closed we set finish to True, so SecondThread will be closed.
finish = True
#After all the program should finish but it raises the error: Tcl_AsyncDelete: async handler deleted by the wrong thread

非常感谢您的帮助!

最佳答案

发生这种情况是因为您在一个线程上创建了 Tk 主窗口,而您没有在进程主线程上运行 UI。当您退出进程时,清理将从进程主线程完成。对于此处的示例,最简单的解决方案是在主线程(进程默认线程)上创建 UI,并且仅将另一个线程用于辅助任务。如果您的实际应用程序无法在主线程上创建 UI,您将需要考虑从它自己的线程中终止 Tk。删除 Tcl 解释器可能会为您做到这一点。

我修改了示例代码以表明将 UI 保留在主线程上可以避免此错误消息。由于您希望在创建 UI 之后但在运行之前创建工作人员,我们可以在 Tk 主循环运行后使用 Tk after 方法启动工作人员。

import time, threading
from tkinter import *
from tkinter import messagebox

class Interface:
def __init__(self):
#threading.Thread.__init__(self)
self.attrib1 = "Attrib from Interface class"
#Main Window
self.mainWindow = Tk()
self.mainWindow.geometry("200x200")
self.mainWindow.title("My GUI Title")
self.mainWindow.protocol("WM_DELETE_WINDOW", self.quit)
#Label
lbCommand = Label(self.mainWindow, text="Hello world", font=("Courier New", 16)).place(x=20, y=20)

#def run(self):

def start(self): #Start
self.mainWindow.mainloop()

#The Interface class contains methods that use attributes from itself and attributes from Process class.
def method1(self):
print(self.attrib1)
print(SecondThread.attrib2)

def quit(self):
if messagebox.askyesno('App','Are you sure you want to quit?'):
#In order to use quit function, mainWindow MUST BE an attribute of Interface.
self.mainWindow.destroy()
self.mainWindow.quit()

class Process(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.attrib2 = "Attrib from Process class"

def run(self):
global finish
while not finish:
print("Proceso infinito")
#Inside the infinite process a method from Interface class is used.
GUI.method1()
time.sleep(3)

finish = False
#Starts the GUI

GUI = Interface()
#Starts the infinity process
SecondThread = Process()
GUI.mainWindow.after(50, SecondThread.start)
#Waits until GUI is closed
GUI.start()
#GUI.join()
print("When GUI is closed this message appears")
#When GUI is closed we set finish to True, so SecondThread will be closed.
finish = True
#After all the program should finish but it raises the error: Tcl_AsyncDelete: async handler deleted by the wrong thread

关于python - Tcl_AsyncDelete 错误多线程 Python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27073762/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com