use tokio::time::sleep;
use std::io::Read;
#[tokio::main]
async fn main() {
let h = tokio::spawn(async move {
let _ = tokio::task::spawn_blocking(|| {
let mut buf = [0, 0, 0, 0];
std::io::stdin().read_exact(&mut buf)
})
.await;
});
sleep(std::time::Duration::from_secs(3)).await;
println!("1234");
}
这段代码会在打印后hang住进程,这是为什么呢? 好像tokio的runtime一直没退出
好像spawn_blocking就是会卡住不让退出,这也太坑了.程序里用了个tokio::io::stdio,给我整的怀疑人生了
1
共 4 条评论, 1 页
评论区
写评论专业解析(技术术语版)
这段代码的卡死问题本质是 Tokio运行时生命周期管理 与 阻塞操作未完成 的冲突,具体流程如下:
代码执行流程分解
关键问题节点
spawn_blocking
线程池中的任务完成(源码见tokio/src/runtime/blocking/pool.rs
的shutdown
方法)stdin().read_exact()
会无限期阻塞等待输入,导致spawn_blocking
线程无法结束h
仍在等待spawn_blocking
,而spawn_blocking
又卡在同步IO解决方案代码
通俗解释(生活化类比版)
想象你开了一家快递站(Tokio Runtime),主线程是老板,
spawn_blocking
是专门处理重物的搬运工小组。事件还原:
read_exact
),于是专门派了个搬运工去门口等着(spawn_blocking
)sleep(3).await
),然后贴出"1234"的公告(println
)卡死原因:
解决方案:
给搬运工配个闹钟(超时机制):
修改关店规则(主动关闭Runtime):
换用更灵活的快递站(使用async-std等替代方案):
关键理解:异步框架中的阻塞操作就像不听话的员工,需要特别的管理策略才能避免"全体等人"的尴尬局面。
When you shut down the executor, it will wait indefinitely for all blocking operations to finish. You can use shutdown_timeout to stop waiting for them after a certain timeout. Be aware that this will still not cancel the tasks — they are simply allowed to keep running after the method returns. It is possible for a blocking task to be cancelled if it has not yet started running, but this is not guaranteed. 当您关闭执行程序时,它将无限期地等待所有阻塞作完成。您可以使用 shutdown_timeout 在特定超时后停止等待它们。请注意,这仍然不会取消任务 — 它们只是被允许在方法返回后继续运行。如果阻塞任务尚未开始运行,则可以取消该任务,但不能保证这一点。
spawn_blocking, 文档中写的
Be aware that tasks spawned using spawn_blocking cannot be aborted because they are not async. If you call abort on a spawn_blocking task, then this will not have any effect, and the task will continue running normally. The exception is if the task has not started running yet; in that case, calling abort may prevent the task from starting. 请注意,使用 spawn_blocking 生成的任务无法中止,因为它们不是异步的。如果您在 spawn_blocking 上调用 abort task,那么这不会有任何影响,任务将继续正常运行。例外情况是任务尚未开始运行;在这种情况下,调用 Abort 可能会阻止任务启动。
看这里https://docs.rs/tokio/latest/tokio/attr.main.html#using-the-multi-thread-runtime 你的h没执行完,tokio的runtime就block了。如果想强制退出,可以abort h。