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

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

问题描述

我希望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闪烁.但是,当我第二次按下按钮而没有重新启动脚本时,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?

推荐答案

我没有发现 logic 错误,并且我确认它是可行的,但是使用了以下更改:

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

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

避免放置在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

Tested with Python:3.4.2

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

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