我使用Raspberry Pi从按钮和一些LED上运行电机。 LED必须根据某些变量执行闪烁模式,并让它们在自己的线程中运行以允许代码继续工作(当然,我从here得到了这个想法。)
问题在于,取决于用户按下按钮的速度(一个序列需要多次推动来设置速度),释放按钮时停止的LED线程有时会在最后一个之前再次调用终止。
这意味着,我认为现在有两个线程,所以当发送阻止LED线程中的run()
动作的命令时,我相信其中一个线程(或者两者都可能)没有#39 ; t得到停止命令,因此在按钮释放后,LED保持闪烁(正如线程所要求的那样)。
所以我认为我正在寻找的方法是确保一次只运行一个LED线程实例。我认为最简单的方法是让LED线程首先终止可能正在运行的LED线程的所有其他实例。我喜欢这个,因为无论哪个灯光从线程中闪烁,它都会停止,并且最近动作中需要闪光的新线程接管。
我该怎么做?我一直在查看isActive()
功能,但我猜不到它的概念,所以我不知道如何使用它。
这是LED线程供参考。其他.py
脚本使用flash_led()
函数调用它,并使用stop_led()
函数停止:
## leds.py. This is imported into the scripts that run the motors and buttons
# LED control Thread (Which-LED, Desired-State On/Off/Flash, Flash-On-Duration, Flash-Off-Duration, Number-Of-Flashes)
class LEDFlash(Thread):
#Initial parameters for an LED Flash command, overwritten by led_flash()
led_pin = led_dict["red_led_1"] #from a dict earlier in the script
flash_on_duration = 1.0
flash_off_duration = 1.0
def __init__(self):
super(LEDFlash, self).__init__()
self.keep_flashing = True
def run(self):
while self.keep_flashing:
GPIO.output(self.led_pin, GPIO.HIGH)
time.sleep(self.flash_on_duration)
GPIO.output(self.led_pin, GPIO.LOW)
time.sleep(self.flash_off_duration)
def stop_flash(self):
self.keep_flashing = False
def flash_led(led, on_time, off_time): # 'flash_led.' added to make flash_thread accessible from the stop_led() function
flash_led.flash_thread = LEDFlash()
flash_led.flash_thread.led_pin = led_dict[str(led)]
flash_led.flash_thread.flash_on_duration = on_time
flash_led.flash_thread.flash_off_duration = off_time
flash_led.flash_thread.start()
def stop_led():
flash_led.flash_thread.stop_flash()
答案 0 :(得分:1)
如果我理解正确,你问的是如何在python中停止一个线程。我喜欢这个主题的现有帖子:Is there any way to kill a Thread in Python?。
话虽如此,你可能还想在释放按钮时考虑 not 停止线程的选项,因为创建线程是一个相对昂贵的操作,并且,如上面的线程所述,你可能不应该直接杀死线程 - 你会想要等待它响应一个事件。如果沿着那条路走下去,你也可能有一个状态变化的事件,并且只是通知现有的线程它应该处于什么状态,而不是创建一个刚刚进入同一状态的全新线程。 。
答案 1 :(得分:1)
来自@MichaelNelson的建议只有一个处理LED的永久线程,这是最好的方法。
但是要直接解决您的问题,您可以在flash_led()
:
if hasattr(flash_led, 'flash_thread'):
stop_led()
这将确保在创建新线程之前销毁旧线程(如果有)。
编辑:旧线程和新线程仍有可能在短时间内处于活动状态;它不应该是你的问题,但如果是,你可以说:
if hasattr(flash_led, 'flash_thread'):
stop_led()
flash_led.flash_thread.join() # wait until old thread completes
你绝对不想杀死一个线程;正如here所解释的那样,终止一个线程是非常危险和混乱的,并且应该只在非常罕见的情况下完成,其中没有其他方法可行。你的情况是完全标准的,可以使用完全干净的代码处理,而不需要使用任何丑陋的东西。
另外,我建议用全局变量替换function属性;它们大致相当,但是当有人读取代码时,全局变量更容易跟踪。换句话说,只需写:
flash_thread = None
def flash_led(led, on_time, off_time):
# you need global statement at the beginning of every function
# in which you modify a global variable
global flash_thread
if flash_thread is not None:
flash_thread.stop_flash() # probably no need to define stop_led()
flash_thread = LEDFlash()
flash_thread.led_pin = ...
...
更好的是重构代码以将其存储为某个控制器对象的实例属性,但这需要更多的工作。