Mar*_*DLF 14 python multithreading tkinter tcl python-3.x
我听说Python中的线程不容易处理,而且它们与tkinter变得更加混乱.
我有以下问题.我有两个类,一个用于GUI,另一个用于无限过程.首先,我启动GUI类,然后是无限进程的类.我希望当你关闭GUI时,它也完成了无限的过程,程序结束了.
代码的简化版本如下:
import time, threading
from tkinter import *
from tkinter import messagebox
finish = False
class tkinterGUI(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global finish
#Main Window
self.mainWindow = Tk()
self.mainWindow.geometry("200x200")
self.mainWindow.title("My GUI Title")
#Label
lbCommand = Label(self.mainWindow, text="Hello world", font=("Courier New", 16)).place(x=20, y=20)
#Start
self.mainWindow.mainloop()
#When the GUI is closed we set finish to "True"
finish = True
class InfiniteProcess(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
def run(self):
global finish
while not finish:
print("Infinite Loop")
time.sleep(3)
GUI = tkinterGUI()
GUI.start()
Process = InfiniteProcess()
Process.start()
Run Code Online (Sandbox Code Playgroud)
当我单击关闭按钮(右上角)时,控制台中会出现以下错误:
Tcl_AsyncDelete: async handler deleted by the wrong thread
Run Code Online (Sandbox Code Playgroud)
我不知道它为什么会发生或它意味着什么.
unu*_*tbu 16
所有Tcl命令都需要来自同一个线程.由于tkinter依赖于Tcl,通常需要使所有tkintergui语句都来自同一个线程.出现问题的原因
mainWindow是在tkinterGui线程中实例化,但是 - 因为mainWindow是 - 的属性,tkinterGui直到tkinterGui在主线程中被销毁才被销毁.
通过不创建mainWindow属性tkinterGui
- 即改变self.mainWindow为... 来避免问题mainWindow.mainWindow当run方法在tkinterGui线程中结束时,这允许 被销毁.但是,通常可以通过使用mainWindow.after调用来完全避免线程:
import time, threading
from tkinter import *
from tkinter import messagebox
def infinite_process():
print("Infinite Loop")
mainWindow.after(3000, infinite_process)
mainWindow = Tk()
mainWindow.geometry("200x200")
mainWindow.title("My GUI Title")
lbCommand = Label(mainWindow, text="Hello world", font=("Courier New", 16)).place(x=20, y=20)
mainWindow.after(3000, infinite_process)
mainWindow.mainloop()
Run Code Online (Sandbox Code Playgroud)
如果要在类中定义GUI,您仍然可以这样做:
import time, threading
from tkinter import *
from tkinter import messagebox
class App(object):
def __init__(self, master):
master.geometry("200x200")
master.title("My GUI Title")
lbCommand = Label(master, text="Hello world",
font=("Courier New", 16)).place(x=20, y=20)
def tkinterGui():
global finish
mainWindow = Tk()
app = App(mainWindow)
mainWindow.mainloop()
#When the GUI is closed we set finish to "True"
finish = True
def InfiniteProcess():
while not finish:
print("Infinite Loop")
time.sleep(3)
finish = False
GUI = threading.Thread(target=tkinterGui)
GUI.start()
Process = threading.Thread(target=InfiniteProcess)
Process.start()
GUI.join()
Process.join()
Run Code Online (Sandbox Code Playgroud)
甚至更简单,只需使用主线程来运行GUI mainloop:
import time, threading
from tkinter import *
from tkinter import messagebox
class App(object):
def __init__(self, master):
master.geometry("200x200")
master.title("My GUI Title")
lbCommand = Label(master, text="Hello world",
font=("Courier New", 16)).place(x=20, y=20)
def InfiniteProcess():
while not finish:
print("Infinite Loop")
time.sleep(3)
finish = False
Process = threading.Thread(target=InfiniteProcess)
Process.start()
mainWindow = Tk()
app = App(mainWindow)
mainWindow.mainloop()
#When the GUI is closed we set finish to "True"
finish = True
Process.join()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
8463 次 |
| 最近记录: |