如何在 Tkinter GUI 中停止并重新启动 python 线程?
How do I stop and restart a python thread within Tkinter GUI?
import tkinter as tk
import tkinter.font
import threading
def sensor_4():
i = 0
while True:
i+=1
t4 = threading.Thread(target=sensor_4)
mainwindow = tk.Tk()
HEIGHT = 700
WIDTH = 800
canvas = tk.Canvas(mainwindow, height = HEIGHT, width = WIDTH)
canvas.pack()
frame = tk.Frame(mainwindow, bg='#08030D') #inside box
frame.place(relx=0, rely=0.1, relwidth = 0.95, relheight = 0.6)
start_sensor4=tk.Button(frame, text = "Press to Start 4", bg='#292230',fg='white',command = t4.start)
start_sensor4.place(relx=0, rely=0.24, relwidth = 0.2, relheight = 0.05)
mainwindow.mainloop()
在代码示例中,我可以通过在 Tkinter GUI 中按下按钮来启动线程函数。我想知道如何在不必 return 的情况下退出线程函数,然后通过单击同一个按钮或单独的按钮重新启动线程。
我还收到错误消息,指出如果我单击启动按钮,线程只能启动一次。
棘手的部分在这里:“没有函数必须 return”。这意味着普通的 thread.join()
调用将挂起,因为线程必须做的工作没有尽头。我们必须使用 threading.Event()
class 来实现这样的结果:
def sensor_4(running_event):
i = 0
while running_event.is_set():
i+=1
def manage_thread(thread, running_event):
if thread.is_alive():
running_event.clear()
thread.join()
else:
running_event.set()
thread.start()
running_event = threading.Event()
t4 = threading.Thread(target=sensor_4, args=(running_event,))
..
..
start_sensor4=tk.Button(frame, text = "Press to Start 4", bg='#292230',fg='white',command = lambda: manage_thread(t4, running_event))
..
这并没有解决多次启动线程的问题,只是解决了使用按钮启动和停止的问题,而函数不必 return。要重新启动线程(如 thread.start()),您必须创建一个具有相同参数的新线程。
我认为“答案”在很大程度上取决于您如何定义您试图解决的设计问题,以及您如何提出问题。
答案似乎解决了您有关停止和重新启动线程的问题。
阅读“字里行间”的内容是不同的。
我认为,根据您的代码,您的设计问题是暂停线程,这与停止和重新启动有很大不同。
@Tresdon 给出了有关线程和异常的讨论的参考。当处于异常状态时,线程还没有死,除非它是未处理的。 ref'd 讨论指出线程已分配资源,一旦被杀死(解除分配),它不是重新启动而是需要新的创建。
要暂停线程,您只需要一个可以在线程代码中读取并由您的主代码切换的标志。如果设置,线程可以“等待”,如果没有设置线程代码运行。根据其他设计标准,等待片段可以是睡眠,或其他可能消耗更多或更少资源的暂停机制。
import tkinter as tk
import tkinter.font
import threading
def sensor_4():
i = 0
while True:
i+=1
t4 = threading.Thread(target=sensor_4)
mainwindow = tk.Tk()
HEIGHT = 700
WIDTH = 800
canvas = tk.Canvas(mainwindow, height = HEIGHT, width = WIDTH)
canvas.pack()
frame = tk.Frame(mainwindow, bg='#08030D') #inside box
frame.place(relx=0, rely=0.1, relwidth = 0.95, relheight = 0.6)
start_sensor4=tk.Button(frame, text = "Press to Start 4", bg='#292230',fg='white',command = t4.start)
start_sensor4.place(relx=0, rely=0.24, relwidth = 0.2, relheight = 0.05)
mainwindow.mainloop()
在代码示例中,我可以通过在 Tkinter GUI 中按下按钮来启动线程函数。我想知道如何在不必 return 的情况下退出线程函数,然后通过单击同一个按钮或单独的按钮重新启动线程。 我还收到错误消息,指出如果我单击启动按钮,线程只能启动一次。
棘手的部分在这里:“没有函数必须 return”。这意味着普通的 thread.join()
调用将挂起,因为线程必须做的工作没有尽头。我们必须使用 threading.Event()
class 来实现这样的结果:
def sensor_4(running_event):
i = 0
while running_event.is_set():
i+=1
def manage_thread(thread, running_event):
if thread.is_alive():
running_event.clear()
thread.join()
else:
running_event.set()
thread.start()
running_event = threading.Event()
t4 = threading.Thread(target=sensor_4, args=(running_event,))
..
..
start_sensor4=tk.Button(frame, text = "Press to Start 4", bg='#292230',fg='white',command = lambda: manage_thread(t4, running_event))
..
这并没有解决多次启动线程的问题,只是解决了使用按钮启动和停止的问题,而函数不必 return。要重新启动线程(如 thread.start()),您必须创建一个具有相同参数的新线程。
我认为“答案”在很大程度上取决于您如何定义您试图解决的设计问题,以及您如何提出问题。
答案似乎解决了您有关停止和重新启动线程的问题。
阅读“字里行间”的内容是不同的。
我认为,根据您的代码,您的设计问题是暂停线程,这与停止和重新启动有很大不同。
@Tresdon 给出了有关线程和异常的讨论的参考。当处于异常状态时,线程还没有死,除非它是未处理的。 ref'd 讨论指出线程已分配资源,一旦被杀死(解除分配),它不是重新启动而是需要新的创建。
要暂停线程,您只需要一个可以在线程代码中读取并由您的主代码切换的标志。如果设置,线程可以“等待”,如果没有设置线程代码运行。根据其他设计标准,等待片段可以是睡眠,或其他可能消耗更多或更少资源的暂停机制。