gpt4 book ai didi

rust - Tokio 任务在完成前退出

转载 作者:行者123 更新时间:2023-12-03 11:29:36 25 4
gpt4 key购买 nike

下面的程序应该从多个线程定期打印,但是 tokio::time::sleep没有按我预期的那样工作:

use tokio::prelude::*; //0.3.4
use tokio::runtime::Builder;
use tokio::time::Duration;

fn main() {
let rt = Builder::new_multi_thread()
.enable_all()
.thread_stack_size(3 * 1024 * 1024)
.build()
.unwrap();

rt.block_on(async {
tokio::spawn(print_thread(1));
tokio::spawn(print_thread(2));
tokio::spawn(print_thread(3));
tokio::spawn(print_thread(4));
});
}

async fn print_thread(thread_num: usize) {
tokio::spawn(async move {
println!("thread{}-start", thread_num);
loop {
tokio::time::sleep(Duration::from_millis(1000)).await;
println!("thread{}-running", thread_num);
}
println!("thread{}-start", thread_num);
});
}
它的输出是
$cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.64s
Running `target/debug/time_test`
thread1-start
thread2-start
thread3-start
thread4-start
$
我希望看到消息 threadN-running ,但没有输出。我不知道为什么程序突然退出。有人可以告诉我原因吗?
我的 Cargo.toml看起来像这样:
[package]
name = "time_test"
version = "0.1.0"
edition = "2018"

[dependencies]
tokio = { version = "0.3", features = ["full"] }
另外,我的 cargo 版本是:
$ cargo --version
cargo 1.48.0 (65cbdd2dc 2020-10-14)

最佳答案

async堵塞:

rt.block_on(async { ... })
不加入产生的 future ,所以它在产生后立即结束。到此结束 block_on还有 main ,前内 task有时间去 sleepprintln! .任务在完成执行之前被终止。
您可以通过包装 block_on 来解决此问题。在一个永无止境的循环中:
loop {
rt.block_on(async {
tokio::spawn(print_thread(1));
tokio::spawn(print_thread(2));
tokio::spawn(print_thread(3));
tokio::spawn(print_thread(4));
});
}
现在 tokio 执行器有足够的时间来生成 tasks , sleep ,并将消息打印到控制台。然而,这个 loop将是昂贵的 cpu 明智的。另一种选择是使用 std::future::pending 从 Rust 1.48 开始稳定。这将创建一个永远不会解决的 future ,代表一个永远不会完成的计算:
rt.block_on(async {
...
});

std::future::pending().await;
unreachable!();
另外,正如@AlexLarionov 所提到的,您实际上正在生成一个 task两次:
// 1st task
tokio::spawn(print_thread(1))

// 2nd task
async fn print_thread(thread_num: usize) {
tokio::spawn(async move { ... });
}
第二次生成是不必要的,您的 print_thread函数可以简化为:
async fn print_thread(thread_num: usize) {
println!("thread{}-start", thread_num);
loop {
tokio::time::sleep(Duration::from_millis(1000)).await;
println!("thread{}-running", thread_num);
}
// Note that this is unreachable
println!("thread{}-start", thread_num);
}
请注意,对于用例 tokio::time::sleep可能不是最好的选择。要按计划定期运行某些程序,您可以使用 tokoi::time::interval :
async fn print_thread(thread_num: usize) {
println!("thread{}-start", thread_num);
let mut interval = tokio::time::interval(Duration::from_millis(100));
loop {
interval.tick().await;
println!("thread{}-running", thread_num);
}
}

关于rust - Tokio 任务在完成前退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65020940/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com