简体   繁体   English

如何在 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()

In the code example, I am able to start the thread function by pressing the button within the Tkinter GUI.在代码示例中,我可以通过按下 Tkinter GUI 中的按钮来启动线程 function。 I am wondering how I can exit the thread function without the function having to return, and restart the thread by clicking on the same button or maybe a separate button.我想知道如何在 function 不必返回的情况下退出线程 function,然后通过单击相同的按钮或单独的按钮重新启动线程。 I also get the error stating that Threads can only be started once, if I click on the start button.如果单击开始按钮,我还会收到错误消息,指出线程只能启动一次。

The tricky part is here: "without the function having to return".棘手的部分在这里:“没有 function 必须返回”。 This means that a vanilla thread.join() call will just hang as there is no end to the work the thread must do.这意味着 vanilla thread.join()调用将挂起,因为线程必须完成的工作没有尽头。 We must use the threading.Event() class to achieve a result like this:我们必须使用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))
..

This does not address the problem of starting the thread more than once but only of starting and stopping using the button without the function having to return.这并没有解决多次启动线程的问题,而只是使用按钮启动和停止,而 function 不必返回。 To restart the thread (as in thread.start()) you must make a new thread with the same parameters.要重新启动线程(如在 thread.start() 中),您必须创建一个具有相同参数的新线程。

I think the "answer" greatly depends on how you define your design problem you are trying to solve and then how you ask the question.我认为“答案”在很大程度上取决于您如何定义您要解决的设计问题以及您如何提出问题。

The answers seem to key off of your question related to stopping and restarting the thread.答案似乎关闭了您与停止和重新启动线程相关的问题。

Reading "between the lines" for what you are trying to accomplish is different.阅读“字里行间”来了解您要完成的工作是不同的。

I think, based on your code, that your design issue is to PAUSE the thread, which is far different from stopping and restarting.我认为,根据您的代码,您的设计问题是暂停线程,这与停止和重新启动有很大不同。

@Tresdon gives ref to discussion about threads and exceptions. @Tresdon 为讨论线程和异常提供参考。 When in the exception, the thread is not yet dead, unless it is unhandled.当处于异常中时,线程尚未死亡,除非它未处理。 The ref'd discussion points out that threads have resources allocated, and once killed (deallocated) it is not a restart but a new creation that is required.参考讨论指出线程分配了资源,一旦被杀死(释放),它就不是重新启动,而是需要重新创建。

To PAUSE the thread, you simply need a flag that can be read in the thread code, and toggled by your main code.要暂停线程,您只需要一个可以在线程代码中读取并由主代码切换的标志。 If set, the thread can "wait", if not set the thread code runs.如果设置,线程可以“等待”,如果没有设置,线程代码运行。 Depending on other design criteria, the wait piece can be a sleep, or some other pausing mech that may consume more or less resources.根据其他设计标准,等待部分可以是睡眠,或其他可能消耗更多或更少资源的暂停机制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM