【问题标题】:tokio join multiple tasks in rusttokio 在 rust 中加入多个任务
【发布时间】:2020-08-26 02:34:19
【问题描述】:

假设有些future存储在一个Vec,其长度由运行时决定,你应该同时加入这些future,你应该怎么做?

显然,通过tokio::join 文档中的示例,手动指定Vec 可能的每个长度,例如 1、2、3,......并且处理可敬的情况应该可以工作。

extern crate tokio;

let v = Vec::new();
v.push(future_1);

// directly or indirectly you push many futures to the vector
 
v.push(future_N);

// to join these futures concurrently one possible way is 

if v.len() == 0 {}
if v.len() == 1 { join!(v.pop()); }
if v.len() == 2 { join!(v.pop(), v.pop() ); }
// ...

我还注意到 tokio::join!当我使用类似

的语法时,将列表作为文档中的参数
tokio::join!(v);

或类似的东西

tokio::join![ v ] /  tokio::join![ v[..] ] / tokio::join![ v[..][..] ]

它只是不起作用

问题来了,是否有任何途径可以更有效地加入这些未来,或者我是否应该错过与文件所说的内容相悖的内容?

【问题讨论】:

  • tokio::join! 采用可变数量的异步表达式,而不是异步值的单个切片/vec。
  • 误解了我在尝试自己解决此问题时制作的 tokio 文档。我假设一块异步代码(异步函数或异步表达式或其他)将被视为 rust 中的期货。而我的问题是如何以更清晰的方式同时加入这些长度变化的“异步表达式”。

标签: rust rust-tokio tokio


【解决方案1】:

您可以使用futures::future::join_all 将您的期货集合“合并”成一个单一的未来,当所有子期货都解决时,它就会解决。

【讨论】:

  • 谢谢。解决了我的问题。不过,我没有找到对称的“join_any(...)”。是不是在别的地方?还是缺席……?
  • 找到docs.rs/tokio/latest/tokio/macro.select.html,但是当第一个分支完成时它会取消其他分支...
【解决方案2】:

join_alltry_join_all,以及来自同一个 crate futures 的更通用的 FuturesOrderedFuturesUnordered 实用程序,作为单个任务执行。如果组成的期货不经常同时准备好执行工作,这可能很好,但是如果您想利用多线程运行时的 CPU 并行性,请考虑将各个期货作为单独的任务生成并等待连接句柄:

use futures::future;

// ...

let outputs = future::try_join_all(v.into_iter().map(tokio::spawn)).await?;

您还可以使用FuturesOrderedFuturesUnordered 组合器在流中异步处理输出:

use futures::stream::FuturesUnordered;
use futures::prelude::*;

// ...

let mut completion_stream = v.into_iter()
    .map(tokio::spawn)
    .collect::<FuturesUnordered<_>>();
while let Some(res) = completion_stream.next().await {
    // ...    
}

使用任务的一个警告是,当产生任务并可能拥有返回的JoinHandle 的未来(例如异步块)被丢弃时,它们不会被取消。需要使用JoinHandle::abort方法显式取消任务。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-22
    相关资源
    最近更新 更多