Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute multiple async functions at once and get the results?

I have tried Tokio tasks, but there are no working examples to execute multiple tasks at once. What is wrong with this code?

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");
}

here is the compiler output

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
like image 349
Alexei Kitaev Avatar asked Aug 18 '20 07:08

Alexei Kitaev


1 Answers

For two futures, like you have, use future::join

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

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

There are variants for three, four, and five input futures: join3, join4, join5.

There is also try_join (and try_join3, try_join4, try_join5) for when your future returns a Result.

The macro join is another way to handle a static number of futures to join.

If you need to support a dynamic number of futures, you can use future::join_all (or try_join_all), but you have to have a vector of all one kind. This is easiest via FutureExt::boxed (or 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;
}

Note that this code can run the futures concurrently but will not run them in parallel. For parallel execution, you need to introduce some kind of tasks.

See also:

  • How can I join all the futures in a vector without cancelling on failure like join_all does?
  • Join futures with limited concurrency
  • How can I perform parallel asynchronous HTTP GET requests with reqwest?
  • How do I create a heterogeneous collection of objects?
  • What is the purpose of async/await in Rust?
  • What is the difference between concurrency and parallelism?
like image 149
Shepmaster Avatar answered Sep 19 '22 08:09

Shepmaster