rust 同时处理多个异步任务,并在一个任务完成退出

发布于:2025-04-08 ⋅ 阅读:(33) ⋅ 点赞:(0)
use std::thread;
use tokio::{
    sync::mpsc,
    time::{sleep, Duration},
};

async fn check_for_one() {
    // 该函数会每秒打印一次 "write"
    loop {
        println!("write");
        sleep(Duration::from_secs(1)).await;
    }
}

async fn start_print_task() -> Result<(), ()> {
    // 在新线程中运行 Tokio 运行时
    thread::spawn(move || {
        // 创建一个新的 Tokio 运行时
        let rt = tokio::runtime::Runtime::new()
            .unwrap_or_else(|e| panic!("Failed to create Tokio runtime: {}", e));

        // 使用 Tokio 运行时执行异步任务
        rt.block_on(async move {
            check_for_one().await;
        });
    });

    // 返回一个已完成的 Future,方便配合 select! 使用
    sleep(Duration::from_secs(1)).await;
    Ok::<(), ()>(())
}

#[tokio::main]
async fn main() {
    // 创建一个只发送“信号”的通道,类型为 ()
    let (tx, mut rx) = mpsc::channel::<()>(1);

    // 启动打印任务,返回一个 Future
    let print_task = start_print_task();

    // 启动另一个异步任务,2 秒后向通道发送“信号”
    tokio::spawn(async move {
        sleep(Duration::from_secs(2)).await;
        let _ = tx.send(()).await;
    });

    // 使用 tokio::select! 监听
    tokio::select! {
        val = rx.recv() => {
            match val {
                Some(_) => println!("rx1 completed first with signal"),
                None => println!("rx1 channel closed"),
            }
        }
        _ = print_task => {
            println!("start_print_task completed");
        }
    }

    println!("main thread exiting");
}

使用select!宏 ,来完成 只要有一个异步任务完成,就会退出异步监听。