使用多个线程多次调用一个方法 [英] Calling a Method several times with several Threads

查看:31
本文介绍了使用多个线程多次调用一个方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个 LED 闪烁,同时我的 Raspberry 正在完成一些工作.我在 Python 脚本中为 LED 使用线程.

I want a LED to flash, while some work is beeing done on my Raspberry. I am using a Thread for the LED in my Python script.

初始代码:

import RPi.GPIO
import time
import threading

pinLED = 10
pinButton = 12

GPIO.setmode(GPIO.BOARD)
GPIO.setup(pinLED, GPIO.OUT)
GPIO.setup(pinButton, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.output(pinLED, 0)

线程的方法:

working = False
def flash():
    status = 0
    while working:
        time.sleep(0.5)
        if status == 0:
            GPIO.output(pinLED, 1)
            status = 1
        else:
            GPIO.output(pinLED, 0)
            status = 0|
    GPIO.output(pinLED, 0)

逻辑:

try:
    while True:
        time.sleep(0.02) #found out that 0.02 is a good value to get every tiny button push and save resources

        if GPIO.input(pinButton) == 1:
            t = threading.Thread(target=flash)
            working = True
            t.start()

            time.sleep(5) #work would be here
            working = False
            t.join()

except Exception as e:
    print(e)
finally:
    GPIO.cleanup()

当我第一次启动脚本并按下按钮时,一切正常,指示灯闪烁.但是当我第二次按下按钮时,没有重新启动脚本,LED 没有闪烁.我打印了一些调试消息并发现 t.start() 被调用,但由于某种原因它什么都不做,也没有抛出异常.不是每次我再按一次按钮 LED 就开始闪烁吗?

When I start the script and press the button the first time, everything is working and the led is flashing. But when i press the button a second time, without restarting the script, the led isn't flashing. I printed some debug messages and found out, that t.start() is called, but for some reason it's doing nothing, also no Exception is thrown. Shouln't the LED start flashing every time I press the button again?

推荐答案

我没有发现逻辑错误,我确认它可以工作,但使用了以下更改:

I found no logic fault and i confirm it works, but used the following changes:

  1. if __name__ == '__main__': 内部启动 main_thread.
    我建议在这个 block 中也移动所有 GPIO 调用.
  1. Starting the main_thread from inside if __name__ == '__main__':.
    I suggest to move also all GPIO calls inside this block.

避免将在启动时执行的代码放在 if __name__ == '__main__' 之外:

Avoid placing code that is executed on startup outside of if __name__ == '__main__':

来自文档:安全导入主模块应该使用 if __name__ == '__main__' 来保护程序的入口点":

From the docs: Safe importing of main module One should protect the "entry point" of the program by using if __name__ == '__main__':

  1. working = False 之后添加了join(),这保证了线程在重新启动之前已经终止.

  1. Added join() after working = False, this guaranteed the thread has terminated befor starting it again.

working = False  
t.join()  

<小时>

我建议将 def flash() 更改为以下内容:
使用 threading.Event() 而不是 global Instance 并将其与 pinLED 一起传递.这概括了 def flash(...) 并允许它与不同的 pinLED 一起使用,甚至是并行的.将 status 定义为 threading.local() 线程安全,因此实例的值对于单独的线程会有所不同.
例如:


I would suggest to change the def flash(), to the following:
Using threading.Event() instead of a global Instance and passing it together with the pinLED. This generalizes the def flash(...) and allow its use with different pinLED, even parallel. Define status as threading.local() threadsafe, so instance’s values will be different for separate threads.
For instance:

def flash(pinLED, flashing):
    status = threading.local()
    status.LED = False
    while flashing.is_set():
        status.LED = not status.LED
        GPIO.output(pinLED, int(status.LED))
        time.sleep(0.5)

    GPIO.output(pinLED, 0)

main_thread 的更改:

def main_thread():
    flashing = threading.Event()
    flashing.clear()

    try:
        while True:
            time.sleep(0.02)  
            if GPIO.input(pinButton) == 1:
                t = threading.Thread(target=flash, args=(pinLED, flashing,))
                flashing.set()
                t.start()

                time.sleep(2)  # work would be here

                flashing.clear()
                t.join()
    ...  

使用 Python:3.4.2 测试

这篇关于使用多个线程多次调用一个方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆