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

使用uasyncio实现两个并发无限循环的技术求助

解决MicroPython uasyncio下的闪烁控制与UDP数据获取问题

我编写了一个程序,用于获取家用气象站传输的UDP数据,其中包含名为“rain_accum”的参数,表示过去一分钟的总降雨量。当“rain_accum”>0时,我希望灯光闪烁;当“rain_accum”==0时,灯光停止闪烁。
作为Python新手,我对MicroPython的uasyncio不太熟悉,折腾3天后虽接近实现,但存在严重的时序问题:闪烁延迟高,且UDP消息丢失。以下是精简后的基础代码,寻求指导:

import uasyncio

async def blink():
    while True:
        print("Here 1")  # 实际代码中对应点亮灯光
        await uasyncio.sleep(1)
        print("Here 2")  # 实际代码中对应熄灭灯光
        await uasyncio.sleep(1)
        
async def getData():
    while True:
        print("Getting data")  # 实际代码中对应接收UDP数据并解析rain_accum
        
        if True:  # 实际代码中替换为 rain_accum > 0 的判断
            await blink()
        print("Next loop")
        await uasyncio.sleep(5)
        
try:
    uasyncio.run(getData())
except KeyboardInterrupt:
    print("Quitting")

核心问题分析

你的代码关键问题是在getData协程中直接await blink()——blink是无限循环的协程,一旦调用await blink(),getData会被彻底阻塞在这一行,无法继续执行后续的循环逻辑,既无法定期获取UDP数据导致消息丢失,也会让blink完全抢占运行时间,造成时序混乱。

修正后的代码

import uasyncio

# 维护闪烁任务的引用,用于控制启动/停止
blink_task = None

async def blink():
    while True:
        print("灯光点亮")
        await uasyncio.sleep(1)
        print("灯光熄灭")
        await uasyncio.sleep(1)

async def getData():
    global blink_task
    while True:
        # 模拟获取UDP数据并解析rain_accum,实际替换为UDP接收逻辑
        # 示例用随机值模拟降雨状态
        import random
        rain_accum = random.randint(0, 1)
        print(f"获取到rain_accum: {rain_accum}")
        
        if rain_accum > 0:
            # 闪烁任务未运行时启动它
            if blink_task is None or blink_task.done():
                blink_task = uasyncio.create_task(blink())
                print("启动闪烁任务")
        else:
            # 闪烁任务运行中时取消它
            if blink_task is not None and not blink_task.done():
                blink_task.cancel()
                blink_task = None
                print("停止闪烁任务")
        
        print("进入下一轮数据获取")
        await uasyncio.sleep(5)  # 实际根据UDP数据频率调整间隔

try:
    uasyncio.run(getData())
except KeyboardInterrupt:
    # 退出前清理任务
    if blink_task is not None and not blink_task.done():
        blink_task.cancel()
    print("程序退出")

关键优化点

  • 并发任务管理:通过uasyncio.create_task()创建blink的独立任务,让getData和blink可以同时执行,避免互相阻塞。
  • 任务状态控制:用全局变量blink_task跟踪闪烁任务的运行状态,根据rain_accum的值动态启动或取消任务,实现闪烁逻辑的精准控制。
  • UDP数据独立性:保持getData循环独立执行,确保能定期接收UDP数据,从根源避免消息丢失问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 06:50:32