複数の非同期関数を一度に実行して結果を取得するにはどうすればよいですか?

Aug 18 2020

Tokioタスクを試しましたが、一度に複数のタスクを実行するための実用的な例はありません。このコードの何が問題になっていますか?

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

回答

6 Shepmaster Aug 18 2020 at 20:06

あなたが持っているように、2つの未来のために、 future::join

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

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

変異体は3、4、および5つの入力先物のためにありますjoin3、join4、join5。

そこにもあるtry_join(とtry_join3、try_join4、try_join5あなたの未来が戻ったときのために)Result

マクロjoinは、参加する先物の静的な数を処理する別の方法です。

動的な数の先物をサポートする必要がある場合は、future::join_all(またはtry_join_all)を使用できますが、すべて1種類のベクトルが必要です。これは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を使用して並列非同期HTTPGETリクエストを実行するにはどうすればよいですか?
  • オブジェクトの異種コレクションを作成するにはどうすればよいですか?
  • Rustでのasync / awaitの目的は何ですか?
  • 並行性と並列性の違いは何ですか?