如何同时执行多个异步函数并获取结果?

10
我尝试过使用Tokio tasks,但没有可执行多个任务的示例。这段代码有什么问题?
fn main() {
    block_on(speak());
}

async fn speak() {
    let hold = vec![say(), greet()];
    let results = join_all(hold).await;
}

async fn say() {
    println!("hello");
}

async fn greet() {
    println!("world");
}

这里是编译器的输出结果

error[E0308]: mismatched types
  --> sync\src\main.rs:14:27
   |
14 |     let hold = vec![say(),greet()];
   |                           ^^^^^^^ expected opaque type, found a different opaque type
...
23 | async fn greet(){
   |                 - the `Output` of this `async fn`'s found opaque type
   |
   = note:     expected type `impl core::future::future::Future` (opaque type at <sync\src\main.rs:19:15>)
           found opaque type `impl core::future::future::Future` (opaque type at <sync\src\main.rs:23:17>)
   = note: distinct uses of `impl Trait` result in different opaque types

1
为什么不使用 join! 宏? - rodrigo
很难回答你的问题,因为它没有包含一个 [MRE]。我们无法确定代码中存在哪些 crates(及其版本)、types、traits、fields等。如果可能的话,您可以在Rust Playground上尝试重现错误,否则可以在全新的Cargo项目中进行,然后[编辑]您的问题以包括额外的信息。这里有一些Rust特定的MRE提示,您可以使用它们来缩小您的原始代码以便在此处发布。谢谢! - Shepmaster
1个回答

14

如果你有两个类似于未来的对象,可以使用future::join函数。

use futures::{executor, future}; // 0.3.5

async fn speak() {
    let (_s, _g) = future::join(say(), greet()).await;
}

有三、四、五个输入的变量版本: join3, join4, join5
还有try_join (和 try_join3, try_join4, try_join5),当您的future返回一个Result时使用。
join是处理静态数量的futures加入的另一种方式。
如果需要支持动态数量的futures,可以使用future::join_all(或try_join_all),但必须拥有所有相同种类的向量。这最容易通过FutureExt::boxed(或FutureExt::boxed_local)实现:
use futures::{executor, future, FutureExt}; // 0.3.5

async fn speak() {
    let futures = vec![say().boxed(), greet().boxed()];
    let _results = future::join_all(futures).await;
}

请注意,这段代码可以同时运行未来任务,但不会并行运行。要进行并行执行,需要引入某种类型的任务。
另请参见: - 如何加入向量中的所有期货,而不像join_all那样在失败时取消? - 使用有限并发加入未来 - 如何使用reqwest执行并行异步HTTP GET请求? - 如何创建异构对象集合? - Rust中async/await的目的是什么? - 并发和并行之间有什么区别?

请标记此问题的已接受答案。这个答案在我有同样问题时帮了我很多。 - spdrman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接