基于GPIO.add_event_detect实现双按钮同时触发多进程函数的咨询
GPIO按钮触发多进程并行执行实现方案
现有代码核心问题
你当前的代码存在两个会导致无法并行执行的错误:
- 进程实例化逻辑错误:
mp.Process(target=my_callback_1(running_time))写法会在创建Process对象时直接同步执行my_callback_1函数,而非将函数作为目标传递给子进程,正确写法需要传递函数引用,参数通过args字段单独传入。 - GPIO回调机制限制:RPi.GPIO的事件回调默认运行在同一个后台线程中,所有触发的回调会串行排队执行,上一个回调未完成时,下一个触发的回调会等待,因此直接把耗时业务函数作为回调必然无法并行。
实现思路
- GPIO事件触发的回调仅做轻量的子进程启动操作,不执行业务逻辑
- 每次按钮触发时单独创建对应业务函数的子进程并启动,天然支持并行
- 可按需添加进程运行状态标记,避免同一按钮短时间重复触发产生多余进程
完整代码示例
import RPi.GPIO as GPIO import multiprocessing as mp import time # 你的业务函数1 def my_callback_1(running_time): # 示例耗时逻辑,可替换为你的实际业务代码 print("进程1启动,运行时长参数:", running_time) time.sleep(running_time) print("进程1执行完成") # 你的业务函数2 def my_callback_2(running_time): print("进程2启动,运行时长参数:", running_time) time.sleep(running_time) print("进程2执行完成") # 按钮1回调:仅负责启动进程1 def start_process1(channel): # 传递参数时注意args需要是元组,单个参数末尾要加逗号 p1 = mp.Process(target=my_callback_1, args=(running_time,)) # 启动子进程,不阻塞主线程 p1.start() # 可选:如果需要避免僵尸进程,可单独维护进程列表后续join,或设置daemon=True # 按钮2回调:仅负责启动进程2 def start_process2(channel): p2 = mp.Process(target=my_callback_2, args=(running_time,)) p2.start() if __name__=="__main__": running_time = 5 # GPIO初始化(可根据你的实际需求调整模式和上下拉配置) GPIO.setmode(GPIO.BCM) GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) # 注册事件,回调改为启动进程的轻量函数,bouncetime可根据实际按键情况调整 GPIO.add_event_detect(19, GPIO.RISING, callback=start_process1, bouncetime=200) GPIO.add_event_detect(26, GPIO.RISING, callback=start_process2, bouncetime=200) # 主线程保持运行 print("等待按钮触发...") try: while True: time.sleep(1) except KeyboardInterrupt: print("退出程序") finally: GPIO.cleanup()
补充说明
如果需要避免同一个按钮被连续按下时启动多个重复进程,可以在启动进程前添加状态判断:用全局变量标记对应进程是否正在运行,进程执行完成后修改标记即可。如果业务逻辑是IO密集型,也可以替换为多线程实现,资源开销更低。
内容的提问来源于stack exchange,提问作者Tomek
相关产品推荐
相关产品推荐

