繁体   English   中英

如何在另一个任务中生成一个长时间运行的 Tokio 任务而不阻塞父任务?

[英]How do I spawn a long running Tokio task within another task without blocking the parent task?

我正在尝试构建一个 object 可以管理来自 websocket 的提要,但能够在多个提要之间切换。

有一个Feed特征:

trait Feed {
    async fn start(&mut self);
    async fn stop(&mut self);
}

实现Feed的三个结构体: ABC

start被调用时,它会启动一个无限循环来监听来自 websocket 的消息,并在收到消息时对其进行处理。

我想实现一个FeedManager ,它维护一个单一的活动提要,但可以接收命令来切换它正在使用的提要源。

enum FeedCommand {
    Start(String),
    Stop,
}

struct FeedManager {
    active_feed_handle: tokio::task::JoinHandle,
    controller: mpsc::Receiver<FeedCommand>,
}

impl FeedManager {
    async fn start(&self) {
        while let Some(command) = self.controller.recv().await {
            match command {
                FeedCommand::Start(feed_type) => {
                    // somehow tell the active feed to stop (need channel probably) or kill the task?

                    if feed_type == "A" {
                        // replace active feed task with a new tokio task for consuming feed A
                    } else if feed_type == "B" {
                        // replace active feed task with a new tokio task for consuming feed B
                    } else {
                        // replace active feed task with a new tokio task for consuming feed C
                    }
                }
            }
        }
    }
}

我正在努力了解如何正确管理所有 Tokio 任务。 FeedManager的核心循环是永远监听进来的新命令,但它需要能够在不阻塞的情况下生成另一个长期存在的任务(这样它就可以监听命令)。

我的第一次尝试是:

if feed_type == "A" {
    self.active_feed_handle = tokio::spawn(async {
        A::new().start().await;
    });

    self.active_feed_handle.await
}
  • 句柄上的.await会导致核心循环不再接受命令,对吗?
  • 我可以省略最后一个.await并让任务仍然运行吗?
  • 我需要以某种方式清理当前活动的任务吗?

我可以通过生成一个任务来生成一个长时间运行的 Tokio 任务而不阻塞父任务——这是任务存在的主要原因 如果您不.await任务,那么您将不会等待任务:

use std::time::Duration;
use tokio::{task, time}; // 1.3.0

#[tokio::main]
async fn main() {
    task::spawn(async {
        time::sleep(Duration::from_secs(100)).await;
        eprintln!(
            "You'll likely never see this printed \
            out because the parent task has exited \
            and so has the entire program"
        );
    });
}

也可以看看:

一种方法是使用 Tokio 的join!()宏,它接受多个期货并等待所有期货。 您可以创建多个期货并join!()它们一起等待它们。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM