You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask控制树莓派传感器:线程仅能启动一次的问题求解

解决Flask控制树莓派传感器扫描启停的线程复用问题

这个问题我之前碰到过好多次,核心问题就是你现在复用了同一个线程实例和事件对象——线程确实只能被启动一次,而且stopevent一旦被set()之后,如果不重置或者换新的,下次启动线程时wait()会直接返回,根本进不了扫描循环。

咱们可以这么改,核心思路是每次启动扫描时创建新的线程和事件实例,而不是复用旧的:

关键修改点

  • 不要把线程和事件设为固定的全局变量,而是用两个全局变量存储当前运行的线程和对应事件,每次启动时重新赋值
  • 在start路由里先检查是否已有线程在运行,避免重复启动导致的错误
  • 在stop路由里,线程结束后清空全局变量,方便下次创建新实例

修改后的完整代码

import threading
from flask import Flask, request, url_for, redirect, render_template

def scan(number, duration):
    # 这里写你的传感器扫描逻辑,比如模拟打印扫描状态
    print(f"Scanning with number={number}, duration={duration}")

class LoopThread(threading.Thread):
    def __init__(self, name, event):
        super(LoopThread,self).__init__()
        self.name = name
        self.event = event
        self.number = 20
        self.duration = 1
    def run(self):
        print('Starting Thread-'+ str(self.name))
        while not self.event.wait(timeout=1.0):
            self.loop_process()
        print('Stopping Thread-'+ str(self.name))
    def loop_process(self):
        scan(self.number, self.duration)

app = Flask(__name__)
# 用全局变量存储当前运行的线程和事件,初始为None
current_thread = None
current_event = None

@app.route("/")
def index():
    print("home page")
    return render_template('home.html')

@app.route("/start")
def start():
    global current_thread, current_event
    # 先检查是否已有线程在运行,避免重复启动
    if current_thread is not None and current_thread.is_alive():
        print("Scan is already running!")
        return redirect(url_for('index'))
    # 创建新的事件和线程实例
    current_event = threading.Event()
    # 线程名用递增数字区分,也可以用时间戳/线程ID
    thread_name = 1 if current_thread is None else int(current_thread.name) + 1
    current_thread = LoopThread(thread_name, current_event)
    current_thread.start()
    print(f"Started new thread: Thread-{thread_name}")
    return redirect(url_for('index'))

@app.route("/stop")
def stop():
    global current_thread, current_event
    if current_thread is None or not current_thread.is_alive():
        print("No scan is running!")
        return redirect(url_for('index'))
    # 设置事件停止线程循环
    current_event.set()
    # 等待线程完全结束
    current_thread.join()
    # 清空全局变量,为下次启动做准备
    current_thread = None
    current_event = None
    print("Scan stopped successfully")
    return redirect(url_for('index'))

if __name__ == '__main__':
    app.run("0.0.0.0", debug=True)

额外说明

  • 线程名的处理:这里用了简单的递增数字,你也可以用threading.get_ident()或者时间戳生成唯一标识,线程名仅用于日志区分,不影响核心功能
  • 状态检查:在启动和停止路由里加了运行状态判断,避免用户重复点击触发异常
  • 事件对象:每次启动都创建新的Event,比重置旧事件的clear()更稳妥,逻辑也更清晰

内容的提问来源于stack exchange,提问作者Willnil Phoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:56:05