运行含无限循环的Rust异步Futures仅执行单个任务的问题排查
Rust异步并发无限循环函数不执行的问题分析与解决
问题根源
Rust的异步执行采用协作式调度模型,执行器不会主动抢占正在运行的Future,必须由当前Future通过await操作主动让出执行权,执行器才会去调度其他待执行的Future。
你写的func_a是无限循环且没有任何await点,执行器启动这个函数后,会一直卡在这个循环里,完全没机会切换到func_b执行。
解决办法
在每个异步函数的循环里加一个主动让出执行权的操作就行,常用的两种方式:
方式1:直接让出执行权
用futures::task::yield_now().await,每次循环都告诉执行器“我先让一让,你去跑别的任务”:
use futures::future::join; use futures::executor::block_on; use futures::task::yield_now; async fn func_a() { loop { println!("Function A is running"); // 主动让出执行权,让其他任务有机会执行 yield_now().await; } } async fn func_b() { loop { println!("Function B is running"); yield_now().await; } } fn main() { let join_handle = join(func_a(), func_b()); block_on(join_handle); }
方式2:用异步sleep模拟工作
如果你的实际逻辑里有耗时操作,别用阻塞式的std::thread::sleep(会卡死整个执行线程),要用异步sleep,既能模拟工作耗时,又能让出执行权:
use futures::future::join; use futures::executor::block_on; use std::time::Duration; use futures::future::sleep; async fn func_a() { loop { println!("Function A is running"); // 模拟500毫秒的异步工作,期间执行器可以调度其他任务 sleep(Duration::from_millis(500)).await; } } async fn func_b() { loop { println!("Function B is running"); sleep(Duration::from_millis(500)).await; } } fn main() { let join_handle = join(func_a(), func_b()); block_on(join_handle); }
注意事项
- 不管用哪种异步运行时(比如Tokio),核心逻辑都是一样的:必须有
await点让执行器切换任务。 - 异步函数里绝对不能用阻塞式操作,不然整个执行线程会被堵死,所有异步任务都停摆。
内容的提问来源于stack exchange,提问作者VoltairePunk
相关产品推荐
相关产品推荐

