9

我有一个asyncrust 函数列表,我想同时执行这些函数,然后等待它们完成。我现在的工作代码是

 async fn start_consumers(&self) {
    for consumer in &self.consumers {
        consumer.consume().await;
    }
}

这不是很准确,因为函数是串行执行的。我正在寻找类似的东西join!,但它适用于动态向量,使用它我应该能够编写类似的东西

 async fn start_consumers(&self) {
    let mut v = Vec::new();
    for consumer in &self.consumers {
        consumer.consume();
    }
    join!(v);
}

现在join!只支持元组。我正在寻找替代方案。类似于JavaScript 中的Promise.all()的东西。

4

5 回答 5

4

同一天我也问了一个类似的问题,但就我而言,我有一个Result包裹在Future. 所以join_all我不得不使用try_join_all

于 2020-08-11T10:36:38.890 回答
4

因此,经过一番搜索,我发现 rust futures 有一个名为join_all的函数,它允许等待一组期货。

 use futures::future::join_all;
 ....

 async fn start_consumers(&self) {
    let mut v = Vec::new();
    for consumer in &self.consumers {
        v.push(consumer.consume());
    }
    join_all(v).await;
 }
于 2020-08-09T14:44:01.340 回答
0

最简单的方法是使用 mpsc 通道,在该通道中,您无需发送消息,而是等待通道关闭,这会在每个发送者都被丢弃时发生。

请参阅此处的 tokio 示例。

于 2022-02-19T17:29:00.453 回答
0

如果您想await/join所有Future来自正常同步函数的 s,并且不关心它们的结果,您可以这样写:

futures::executor::block_on(async{futures::join!(future1, future2, future3, ...)});

您可以将此宏block_all用于更符合人体工程学的用法:

macro_rules! block_all {
    ($($future:expr),*) => {{
        futures::executor::block_on(async{futures::join!($($future),*)})   
    }};
}

用法:

block_all!(future1, future2, ...);
于 2021-07-29T11:07:42.073 回答
0

join_all/try_join_all做的伎俩,但输出是Vec收集期货的结果。在上面的修改示例中,组合的未来会产生 a Vec<()>,这不会导致分配,甚至扩展此向量的操作也应在发布版本中优化为无。

即使在您确实需要输出的情况下,当它们以异步方式进入流时处理它们可能是值得的,而不是等待所有它们被收集。为此,您可以使用FuturesOrderedor FuturesUnordered,这取决于您是否关心在流产生的输出中保留原始期货的顺序,或者更喜欢按完成顺序接收输出。FuturesUnordered不需要缓冲结果,并且可能比FuturesOrdered由相同期货组成的更快完成。

于 2021-10-01T22:23:02.463 回答