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

Tokio spawn启动的no_msg_pro函数首次循环不执行问题排查

问题:Tokio异步任务延迟执行的原因

代码示例

use std::thread::sleep;
use std::time;
use std::sync::atomic::{AtomicU32, Ordering};
use tokio::time::Duration;

static REQUEST_RECV_V2: AtomicU32 = AtomicU32::new(0);

async fn no_msg_pro(s: String) {
    println!("exectue no_msg_pro fun - str: {} begin!", s);
    tokio::time::sleep(time::Duration::from_secs(5)).await;
    //sleep(time::Duration::from_secs(5));
    println!("exectue no_msg_pro fun - str: {} end!", s);
}

#[tokio::main]
async fn main() {
    tokio::spawn(async {
        loop {
            sleep(time::Duration::from_secs(10));
            REQUEST_RECV_V2.fetch_add(1, Ordering::Relaxed);
            let s = format!("value--{:?}", REQUEST_RECV_V2);
            println!("run process_msg fun - handle: {:?}", s);
            tokio::spawn(async move {
                no_msg_pro(s).await;
            });
        }
    });

    tokio::time::sleep(Duration::from_secs(100)).await;
}

运行结果

run process_msg fun - handle: "value--1"
run process_msg fun - handle: "value--2"
exectue no_msg_pro fun - str: value--1 begin!
exectue no_msg_pro fun - str: value--1 end!

原因分析

核心问题在于错误使用了阻塞式的sleep:

  • loop循环里调用的std::thread::sleep是同步阻塞操作,会让当前线程直接暂停10秒,期间Tokio的异步调度器完全无法工作。
  • Tokio默认采用单线程调度模型(#[tokio::main]未指定多线程时),第一次进入loop后,std::thread::sleep(10秒)直接阻塞了唯一的工作线程,导致后续tokio::spawn出来的no_msg_pro任务没有机会被调度执行。
  • 第一次10秒阻塞结束后,代码完成spawn操作立刻进入第二次loop的std::thread::sleep,再次阻塞线程。直到第二次10秒结束,线程被释放,Tokio调度器才终于能处理之前堆积的no_msg_pro任务,所以此时才会执行对应"value--1"的函数。

修复方法很简单:把loop里的std::thread::sleep替换为Tokio提供的异步sleep——tokio::time::sleep(Duration::from_secs(10)).await,这样不会阻塞线程,调度器可以在等待期间正常处理其他异步任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:40:24