วิธีเรียกใช้ฟังก์ชัน async หลายรายการพร้อมกันและได้รับผลลัพธ์อย่างไร

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

สำหรับสองฟิวเจอร์สเช่นเดียวกับที่คุณมีให้ใช้ future::join

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

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

มีสายพันธุ์สำหรับสามสี่และห้าฟิวเจอร์สที่มีการป้อนข้อมูล: join3, ,join4join5

นอกจากนี้ยังมีtry_join(และtry_join3, try_join4, try_join5) Resultเมื่อในอนาคตของคุณส่งกลับ

มาโครjoinเป็นอีกวิธีหนึ่งในการจัดการฟิวเจอร์สจำนวนคงที่ที่จะเข้าร่วม

หากคุณต้องการรองรับฟิวเจอร์สจำนวนไดนามิกคุณสามารถใช้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 ทำได้อย่างไร
  • เข้าร่วมฟิวเจอร์สด้วยภาวะพร้อมกันที่ จำกัด
  • ฉันจะดำเนินการตามคำขอ HTTP GET แบบอะซิงโครนัสแบบขนานกับ reqwest ได้อย่างไร
  • ฉันจะสร้างคอลเล็กชันวัตถุที่แตกต่างกันได้อย่างไร
  • จุดประสงค์ของ async / await ใน Rust คืออะไร?
  • อะไรคือความแตกต่างระหว่างภาวะพร้อมกันและความขนาน?