rust - Tokio 任务可以优雅地终止整个运行时吗?

标签 rust rust-tokio

我使用如下代码启动 Tokio 运行时:

tokio::run(my_future);

我的 future 将根据各种条件启动一系列任务。

其中一项任务负责确定程序何时应关闭。但是,我不知道如何让该任务优雅地终止程序。理想情况下,我希望找到一种方法让此任务导致 run 函数调用终止。

下面是我想编写的程序类型的示例:

extern crate tokio;

use tokio::prelude::*;

use std::time::Duration;
use std::time::Instant;

use tokio::timer::{Delay, Interval};

fn main() {
    let kill_future = Delay::new(Instant::now() + Duration::from_secs(3));

    let time_print_future = Interval::new_interval(Duration::from_secs(1));

    let mut runtime = tokio::runtime::Runtime::new().expect("failed to start new Runtime");
    runtime.spawn(time_print_future.for_each(|t| Ok(println!("{:?}", t))).map_err(|_| ()));
    runtime.spawn(
        kill_future
            .map_err(|_| {
                eprintln!("Timer error");
            })
            .map(move |()| {
                // TODO
                unimplemented!("Shutdown the runtime!");
            }),
    );
    // TODO
    unimplemented!("Block until the runtime is shutdown");
    println!("Done");
}

shutdown_now看起来很有希望,但经过进一步调查,它可能行不通。特别是,它需要运行时的所有权,并且 Tokio 可能不会允许主线程(创建运行时的地方)和一些随机任务拥有运行时。

最佳答案

您可以使用 oneshot channel从运行时内部到外部进行通信。当延迟到期时,我们通过 channel 发送一条消息。

在运行时之外,一旦我们收到该消息,我们就会启动运行时的关闭并等待它完成。

use std::time::{Duration, Instant};
use tokio::{
    prelude::*,
    runtime::Runtime,
    sync::oneshot,
    timer::{Delay, Interval},
}; // 0.1.15

fn main() {
    let mut runtime = Runtime::new().expect("failed to start new Runtime");

    let (tx, rx) = oneshot::channel();

    runtime.spawn({
        let every_second = Interval::new_interval(Duration::from_secs(1));
        every_second
            .for_each(|t| Ok(println!("{:?}", t)))
            .map_err(drop)
    });

    runtime.spawn({
        let in_three_seconds = Delay::new(Instant::now() + Duration::from_secs(3));
        in_three_seconds
            .map_err(|_| eprintln!("Timer error"))
            .and_then(move |_| tx.send(()))
    });

    rx.wait().expect("unable to wait for receiver");
    runtime
        .shutdown_now()
        .wait()
        .expect("unable to wait for shutdown");

    println!("Done");
}

另请参阅:

关于rust - Tokio 任务可以优雅地终止整个运行时吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54522623/

相关文章:

linux - Rust 无法在 Linux 中编译为可执行文件

arrays - 有没有办法在 Rust 中通过枚举索引数组?

struct - 更新具有私有(private)字段的 Rust 结构的公共(public)字段

rust - 如何检索在 Rust 中使用 docopt 时使用的子命令?

rust - 如何使方法流不可知?

rust - 如何在 Tokio 中安排重复任务?

asynchronous - 如何在 Tokio future 链的多个分支中使用 TcpStream?

rust - 我如何处理 Rust 中的包装器类型不变性?

rust - 包装 AsyncRead

rust - 为什么迭代器的实现在异步上下文中不够通用?