首页 > 解决方案 > Python:如何重新启动被标志停止的线程

问题描述

我需要根据某些条件停止/启动线程。我可以使用标志来启动它然后停止它,但是当我尝试再次启动它时,我得到RuntimeError: threads can only be started once

例如,在以下代码中,用户按下退出键来启动或停止标签闪烁。第一次调用开始,第二次调用停止,但第三次调用我得到运行时错误。

from tkinter import *
import threading
import time

class App:
    def __init__(self, master):
        self.label = Label(text="TEXT?", font=('Helvetica', 30))
        self.label.pack()
        self.labelFlash = False
        self.t = threading.Thread(target=self.flash)
        root.bind("<Escape>", self.flashEvent)
    def flashEvent(self, event):
        if self.labelFlash == False:
            self.labelFlash = True
            self.t.start()
        elif self.labelFlash == True:
            self.labelFlash = False
            print(self.labelFlash)
    def flash(self):
        while self.labelFlash == True:
            self.label.config(bg='red')
            root.update()
            time.sleep(.5)
            self.label.config(bg='green')
            root.update()
            time.sleep(.5)
root = Tk()
app = App(root)
root.mainloop()

我将如何重新启动线程而不会出现此错误?谢谢你。

标签: tkinterpython-3.6python-multithreading

解决方案


您可以使用threading.Event对象来控制线程何时回调到 gui。但是在事件循环线程之外调用 gui 是非法的,最终会导致崩溃。相反,使用该after()方法在循环中安排定时事件。此事件可以安全地更改背景颜色,并且可以取消以暂停操作。

from tkinter import *
import threading
import time

class App:
    def __init__(self, master):
        self.master = master
        self.flash_colors = ['red', 'green']
        self.cur_color = 0
        self.flash_timer_id = None
        self.label = Label(text="TEXT?", font=('Helvetica', 30))
        self.label.pack()
        root.bind("<Escape>", self.flashEvent)

    def flashEvent(self, event):
        if self.flash_timer_id is None:
            # start flashing
            self.flash()
        else:
            # stop flashing
            self.master.after_cancel(self.flash_timer_id)
            self.flash_timer_id = None

    def flash(self):
        self.label.config(bg=self.flash_colors[
            self.cur_color%len(self.flash_colors)])
        self.cur_color += 1
        root.update()
        # (delay in mS)
        self.flash_timer_id = self.master.after(500, self.flash)

root = Tk()
app = App(root)
root.mainloop()

推荐阅读