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

Tokio任务内嵌套spawn子任务未按预期执行问题排查

代码错误说明

你的代码违反了Tokio异步运行时的协作式调度规则,存在两个核心问题:

  • 异步上下文中误用阻塞式线程睡眠
    你在asfunc中使用的std::thread::sleep是同步阻塞调用,会直接冻结当前操作系统线程,不会向Tokio调度器交还执行权。Tokio的调度逻辑要求异步代码在等待时间、IO等事件时主动让出线程资源,否则同线程上挂载的其他任务会被完全饿死,始终拿不到执行机会。
  • 异步上下文中误用同步阻塞通道
    你使用的std::sync::mpsc是标准库提供的同步通道,它的recv()方法同样是阻塞调用:调用后会一直卡住当前线程直到收到消息,完全不会让出执行权。你在run_test末尾和wrapper函数中都直接调用了阻塞的recv(),进一步加剧了线程阻塞问题。

你只能看到one的输出,本质是调度器先调度了关联one的任务链,阻塞的睡眠、收消息逻辑占住了工作线程,wrapper相关的任务自始至终没有拿到执行资源。

修正方案

按照异步运行时的规范替换对应组件即可:

  1. 用Tokio提供的异步睡眠tokio::time::sleep替换std::thread::sleep,睡眠等待时会主动让出执行权
  2. 用Tokio提供的异步通道tokio::sync::mpsc替换标准库同步通道,收消息时使用异步的recv()方法,不会阻塞工作线程

修正后的th_test.rs完整代码如下:

use tokio::sync::mpsc::Sender;
use tokio::time;

async fn wrapper() {
    // 替换为tokio异步通道,设置合理的通道缓冲区大小
    let (tx, mut rx) = tokio::sync::mpsc::channel::<String>(10);
    
    tokio::task::spawn(async move {
        asfunc(tx,"two".to_string()).await;
    });

    // 调用异步recv方法收消息
    while let Some(msg) = rx.recv().await {
        println!("[wrapper] {:?}",msg);
    }
}

async fn asfunc(tx: Sender<String>, name: String) {
    loop {
        // 替换为tokio异步睡眠
        time::sleep(time::Duration::from_secs(1)).await;
        let now = time::Instant::now(); 
        // 异步通道的send也需要await
        tx.send(format!("[{}] {:?}",name, now)).await.unwrap();
    }
}

pub async fn run_test() {    
    // 替换为tokio异步通道
    let (tx, mut rx) = tokio::sync::mpsc::channel::<String>(10);
    
    tokio::task::spawn(async move {
        asfunc(tx,"one".to_string()).await;
    });

    tokio::task::spawn(async move {
        wrapper().await;
    });

    // 调用异步recv方法收消息
    while let Some(msg) = rx.recv().await {
        println!("[asfunc] {:?}",msg);
    }
}

main.rs不需要修改,保持原有结构即可。运行后你会看到one和two的日志按1秒间隔交替输出,符合预期。

额外提示:如果确实需要在异步代码中调用无法替换的阻塞逻辑(比如读取同步文件、执行CPU密集型计算),必须用tokio::task::spawn_blocking把阻塞逻辑放到专门的阻塞线程池中执行,避免卡死Tokio的异步工作线程。

内容的提问来源于stack exchange,提问作者Peter K.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 11:24:38