当 tokio 运行时关闭时,在 Rust 中使用 tokio::spawn 创建的任务也会被删除吗?

yjl*_*lee 3 rust rust-tokio

我正在测试主线程终止时使用 tokio::spawn 创建的任务的行为方式。根据tokio 文档,当运行时关闭时,所有任务都会被删除。

无法保证生成的任务将执行完成。当运行时关闭时,所有未完成的任务都将被删除,无论该任务的生命周期如何。

然而,当测试如下运行时,即使运行时终止,任务似乎也没有终止。

Cargo.toml

[package]
name = "tokio_test"
version = "0.1.0"
edition = "2021"

[dependencies]
tokio = { version = "1", features = ["rt", "test-util", "macros", "rt-multi-thread"]}
Run Code Online (Sandbox Code Playgroud)

主程序.rs

use std::{thread, time};
#[tokio::main]
async fn main() {
    println!("tokio test - main thread...");
    tokio::spawn(async move {
        let mut i = 0;
        loop {
            println!(
                "tokio test - tokio spawn(worker) thread... sleep(1): {}/10",
                i
            );
            thread::sleep(time::Duration::from_millis(1000));
            i += 1;
         
            if i > 3 {
                break;
            }
        }
      
    });
    thread::sleep(time::Duration::from_millis(1000));
    println!("tokio test - main thread... closed ");
}
Run Code Online (Sandbox Code Playgroud)

输出

tokio test - main thread...
tokio test - tokio spawn(worker) thread... sleep(1): 0/10
tokio test - main thread... closed 
tokio test - tokio spawn(worker) thread... sleep(1): 1/10
tokio test - tokio spawn(worker) thread... sleep(1): 2/10
tokio test - tokio spawn(worker) thread... sleep(1): 3/10
Run Code Online (Sandbox Code Playgroud)

问题

Q1:如果我希望任务在运行时终止时自动终止,我是否必须直接通过任务的 JoinHandle 来终止它们?

Q2:如果我在 tokio::spawn 中调用 tokio::spawn,嵌套任务将不起作用。我不能像这样嵌套 tokio::spawn 吗?(它显示与输出相同的结果)

tokio::spawn(async move {
    let mut i = 0;
    loop {
        println!(
            "tokio test - tokio spawn(worker) thread... sleep(1): {}/10",
            i
        );
        thread::sleep(time::Duration::from_millis(1000));
        i += 1;
        
        /* nested spawn */
        tokio::spawn(async move {
            println!("worker thread in worker, sleep(1): 10");
            thread::sleep(time::Duration::from_millis(1000));
        });

        if i > 3 {
            break;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

Cha*_*man 7

这是因为您正在使用std::thread::sleep(). sleep()Tokio 无法控制阻塞函数,并且无法在执行时停止任务。它只能停止任务await

如果替换std::thread::sleep()为,则完成tokio::time::sleep().await后停止。这是一个证明任务确实被删除的游乐场main()

  • Playground 代码片段还应该在主任务中使用 `tokio::task::sleep` 和 `.await`,以便内部任务有机会运行。现在它只在创建时运行一次,而不是在睡眠期间运行。 (2认同)