对如何正确地要求线程停止进行了一些研究之后,我陷入了意外行为。
我正在做一个个人项目。我的目标是在专门用于家庭医学的RaspberryPi上运行一个程序。
我的代码结构如下:
这是我的工作方式:
import schedule
from pynput import keyboard
import threading
first_thread = threading.Thread(target=heating, name="heating")
second_thread = threading.Thread(target=keyboard, name="keyboard")
first_thread.start()
second_thread.start()
stop_event = threading.Event()
我的加热程序定义为:
def heating():
def job():
GPIO.output(4,GPIO.HIGH)
return
schedule.every().day.at("01:00").do(job)
while True:
schedule.run_pending()
time.sleep(0.5)
我的键盘监视器定义如下:
def keyboard():
def on_press(key):
if key == keyboard.Key.f4:
shutter_thread = threading.Thread(name="shutter", target=shutter, args=(stop_event,))
shutter_thread.start()
if key == keyboard.Key.f5:
stop_event.set()
with keyboard.Listener(on_press=on_press,on_release=on_release) as listener:
listener.join()
我的shutter
线程目标类似于加热对象:
def shutter(stop_event):
def open():
GPIO.output(6,GPIO.HIGH)
return
t = threading.currentThread()
schedule.every().day.at("22:00").do(open)
while not stop_event.is_set():
schedule.run_pending()
time.sleep(0.5)
问题是每次我按下键启动shutter
线程时,都会调用快门例程,但是:
job
例程中的shutter
执行了两次job
现在每次也按计划执行两次!shutter
线程停止,heating
(第一个)线程恢复到其原始(且正确)的行为,但是shutter
线程却执行了不停我不知道为什么启动这个新线程会在另一个线程的行为上产生这种修改。为什么我的停止事件无法正常工作?
我在做什么错了?
答案 0 :(得分:0)
由于您使用schedule
框架来管理任务,因此一个干净的解决方案是使用相同框架的API来取消作业(而不是使用threading.Event
)。这样,任务管理将保留在schedule
中,而用户交互则由threading
处理。
def keyboard():
tasks = []
def on_press(key):
if key == keyboard.Key.f4:
# Shutter task.
tasks.append(
schedule.every().day.at("22:00").do(lambda: GPIO.output(6,GPIO.HIGH))
)
if key == keyboard.Key.f5:
schedule.cancel_job(tasks.pop(-1))
with keyboard.Listener(on_press=on_press,on_release=on_release) as listener:
listener.join()
# Heating task.
schedule.every().day.at("01:00").do(lambda: GPIO.output(4,GPIO.HIGH))
# Start keyboard listener.
ui = threading.Thread(target=keyboard)
ui.start()
while True:
schedule.run_pending()
time.sleep(0.5)
答案 1 :(得分:0)
即使a_guest解决方案是干净的,我也可以为那些可能遇到类似情况的人分享第二种解决方案。
一种可行的解决方案是在不同的线程中定义特定的调度程序,而不使用默认的调度程序。
插图:
def heating():
def job():
GPIO.output(4,GPIO.HIGH)
return
heat_sched = schedule.Scheduler()
heat_sched.every().day.at("01:00").do(job)
while True:
heat_sched.run_pending()
time.sleep(1)
def shutter(stop_event):
def open():
GPIO.output(6,GPIO.HIGH)
return
shutter_sched = schedule.Scheduler()
shutter_sched.every().day.at("22:00").do(open)
while True:
if not stop_event.is_set():
shutter_sched.run_pending()
time.sleep(0.5)
else:
shutter_sched.clear()
return