如何给守护线程一个停止事件



我正试图让我的头在python线程,我拼凑了一个简单的tkinter UI,可以运行后台任务,以更好地理解它是如何工作的。
我似乎已经到了我可以创建一个单独的线程并与GUI交互的地步,但是当我第二次尝试执行任务时,问题就来了。

我相信我缺少的是一种告诉守护进程何时停止线程的方法。
我的代码如下:

import threading
import tkinter as tk
from collections import deque
from threading import Thread
from random import randint
from time import sleep

class Emitter:
def __init__(self):
self.stop_event = threading.Event()
self.thread = Thread(target=self.emit_text)
self.running = False
def emit_text(self):
sleep(3)
messageQueue.append(f'Random number: {randint(0, 100)}')
# self.thread.set()
def start_emit(self):
ui.consume_text()
self.thread.setDaemon(True)
self.thread.start()

class UI:
def __init__(self):
self.root = tk.Tk()
self.label = tk.Label(self.root, text='Original text')
self.label.pack()
start = tk.Button(self.root, text='Start Download', command=lambda x=Emitter(): x.start_emit())
start.pack()
def consume_text(self):
try:
self.label['text'] = messageQueue.popleft()
except IndexError:
self.root.after(ms=1000, func=self.consume_text)

messageQueue = deque()
ui = UI()
ui.root.mainloop()

我试着去理解其他的答案,但我不能理解你如何告诉守护进程/线程它的条件停止是什么。
程序按预期工作,你第一次点击按钮,但如果你试图再次点击它,它给出了错误RuntimeError: cannot set daemon status of active thread,即使我已经等待发射器完成它的任务

感谢@Solomon Slow的评论,我遇到的问题是我试图重新启动线程,但实际上我应该每次都创建一个新的线程。
为了解决这个问题,我改变了我的类Emitter类,在每次调用start_emit()时创建一个新线程。

固定类:

class Emitter:
def __init__(self):
self.stop_event = threading.Event()
def emit_text(self):
sleep(3)
messageQueue.append(f'Random number: {randint(0, 100)}')
def start_emit(self):
ui.consume_text()
thread = Thread(target=self.emit_text)
thread.start()

我还删除了self.thread.setDaemon(True)行。

最新更新