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

Django结合threading使用全局变量控制树莓派硬件的问题咨询

问题原因与解决方案

为什么修改cfg.RUNNING不生效

Django默认的开发模式会启动两个独立进程:一个负责监听代码变更自动重载,另一个负责处理用户请求。你在apps.py的ready方法中启动的runner线程运行在自动重载的主进程内,而视图函数修改的cfg.RUNNING是请求处理进程内的变量,两个进程内存空间完全隔离,变更自然无法互相感知。就算切换到生产环境,只要启动了多个worker进程,同样会遇到这个问题。

临时验证方法

如果你只是想快速验证当前逻辑的正确性,可以关闭Django的自动重载,启动服务时执行:

python manage.py runserver --noreload

此时服务只会启动一个进程,你写的测试代码就能正常运行了。

符合需求的长期架构方案

针对你提到的4个实现目标,推荐的架构设计如下:

  • 统一管理串口和长运行任务
    单独启动一个独立的后台常驻进程,专门负责串口初始化、游戏线程管理、硬件交互逻辑,不要和Django的请求处理进程混在一起。串口实例只保存在这个进程的全局变量中,避免多进程访问串口冲突,也解决了串口对象无法序列化存数据库的问题。
  • 进程间通信传递指令
    Django视图和后台进程之间用轻量的IPC机制通信,树莓派场景推荐用Redis做消息队列/状态存储:
    • 视图收到启动/终止任务的请求时,往Redis的指定频道发指令,或者写入任务队列
    • 后台进程订阅对应频道/轮询任务队列,收到启动指令后,从自身全局变量拿到串口实例,启动新的游戏线程执行逻辑
  • 线程安全的终止机制
    每个游戏线程用threading.Event做终止标识,不要用普通布尔变量:
    import threading
    class GameThread(threading.Thread):
        def __init__(self, serial_port, name):
            super().__init__(daemon=True)
            self.serial_port = serial_port
            self.name = name
            self.stop_event = threading.Event()
            # 要暴露给前端的状态变量
            self.status = {"progress": 0, "current_step": ""}
    
        def run(self):
            # 游戏逻辑循环
            while not self.stop_event.is_set():
                # 执行硬件操作、游戏逻辑
                pass
            # 退出前做资源清理
    
    终止线程时只要调用对应线程的stop_event.set()即可,线程会在下次循环检测到后安全退出。所有运行中的线程存在后台进程的字典里,用任务ID做key,方便快速查找操作。
  • 线程状态同步
    后台进程定期把所有运行中线程的状态变量写入Redis,Django视图收到状态查询请求时,直接读Redis里的数据返回给前端展示即可,不需要直接访问游戏线程。
  • 额外注意:串口是独占资源,多线程操作时要加threading.Lock锁,每次读写串口前获取锁,操作完成后释放,避免数据错乱。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 21:06:05