gpt4 book ai didi

Python 从另一个线程启动/停止线程会导致意外行为

转载 作者:太空宇宙 更新时间:2023-11-04 02:21:20 28 4
gpt4 key购买 nike

在对如何正确请求线程停止进行一些研究后,我陷入了一种意想不到的行为。

我正在做一个个人项目。我的目标是在专用于家庭自动化的 RaspberryPi 上运行一个程序。

我的代码结构如下:

  1. 第一个线程专用于调度:每天同一时间,我在 GPIO 输出上发送信号
  2. 第二个线程专用于监控键盘的手动事件
  3. 每当按下特定键时,我想启动一个新线程,该线程专用于另一个例程,就像我的第一个线程一样

下面是我的处理方式:

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线程不会停止

我不知道为什么启动这个新线程会在另一个线程的行为中产生这样的修改。为什么我的停止事件不起作用?

我做错了什么?

最佳答案

由于您正在使用 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)

关于Python 从另一个线程启动/停止线程会导致意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51565356/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com