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

Rust基于Tokio多线程运行异步任务及panic报错排查

问题原因

触发该panic的核心逻辑如下:

  1. #[tokio::main]宏会自动生成一个全局的Tokio运行时,将标记的async main函数作为运行时内的初始任务执行,也就是说你的main函数本身已经运行在异步上下文里。
  2. 你在这个异步上下文内部又手动通过Builder::new_multi_thread()构建了第二个独立的Tokio运行时rt。
  3. Tokio运行时在drop(析构)时会阻塞等待自身持有的所有任务完成、完成全部资源回收,这个阻塞操作不允许在异步上下文中执行。
  4. 你没有手动对rt做关闭处理,当main函数执行到末尾时,rt会自动离开作用域触发析构,刚好命中了“异步上下文内阻塞drop运行时”的报错条件。

报错信息里的Cannot drop a runtime in a context where blocking is not allowed就是对这个场景的直接描述。

修复方式

根据你的需求二选一即可:

  • 如果不需要自定义工作线程数这类特殊运行时配置,直接使用#[tokio::main]生成的默认运行时即可,不需要手动新建第二个rt,提交任务直接调用全局的tokio::spawn:
async fn routine(millis: u64) {
    tokio::time::sleep(std::time::Duration::from_millis(millis)).await;
}

#[tokio::main]
async fn main() {
    let handles: Vec<tokio::task::JoinHandle<_>> = (1..10_u64).map(|i| {
        tokio::spawn(routine(i))
    }).collect();

    for handle in handles {
        handle.await.unwrap();
    }
}
  • 如果确实需要自定义运行时参数(比如指定2个工作线程),就去掉#[tokio::main]宏,在同步的main函数入口手动构建运行时,保证运行时的析构发生在同步上下文:
async fn routine(millis: u64) {
    tokio::time::sleep(std::time::Duration::from_millis(millis)).await;
}

fn main() {
    let rt = tokio::runtime::Builder::new_multi_thread()
        .worker_threads(2)
        .enable_all()
        .build()
        .unwrap();

    // 通过block_on在自定义运行时上执行异步逻辑
    rt.block_on(async {
        let handles: Vec<tokio::task::JoinHandle<_>> = (1..10_u64).map(|i| {
            tokio::spawn(routine(i))
        }).collect();

        for handle in handles {
            handle.await.unwrap();
        }
    });
    // 此处rt离开作用域析构,处于同步上下文,不会触发panic
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:30:45