Rust での await

Nilesh Katuwal 2022年8月18日
Rust での await

この記事では、Rust での await の意味を学びます。

Rust で await

async-await は、一時停止し、実行時に制御を放棄して、中断したところから実行を再開できる関数を作成するための手法です。通常、これらの一時停止は I / O を待機するために使用されますが、さまざまな目的に使用できます。

async-await は、JavaScript または C# でおなじみかもしれません。ただし、Rust の機能の実装には、いくつかの重要な変更があります。

async-await を利用するには、fnasync fn に置き換える必要があります。

async fn new_fxn() -> u32 { .. }

従来の関数とは対照的に、async fn を呼び出してもすぐには効果がありません。代わりに future を返します。

計算は中断され、実行されるのを待っています。 .await 演算子を使用して future を実行します。

async fn second_fxn () {
    let future = new_fxn();

    let result: u32 = future.await;
    ...
}

この例は、Rust と他の言語の最初の違いを示しています。future を待つのではなく、future.await と記述します。この構文は、Rust の ? とより適切に相互作用します。I/O で一般的なエラーを伝播するための演算子。

future.await? と書くことができます欠点を負い、たくさんの結果を待つために。さらに、チェーンの方法を簡単にするという利点があります。

await という用語は、非同期関数のコンテキスト内でのみ使用でき、非同期関数のみを待機できます。

Rust の future は緩いです。デフォルトでは、最初のポーリングが実行されるまでは何もしません。future を待つとき、それは調査されます。

たとえば、プログラムの開始時に future を返す関数を呼び出したが、プログラムの終了まで await しない場合、実際のリクエストは await するまで実行されません。

例:

use std::thread;
use tokio::time::{sleep, Duration};
use futures::future;

#[tokio::main]
async fn main(){
    let mut await_demo = Vec::new();

    for count in 1..=5
    {
        await_demo.push(tokio::spawn(async move{
            println!("Start the thread {count}, id= {:?}", thread::current().id());
            sleep (Duration::from_millis(5000)).await;
            println!("end the thread {count}, id = {:?})", thread::current().id());
        }));
    }
    future::join_all (await_demo).await;
}

最初に、5つの futures(5つの async ブロック)が作成され、各 futuresleep future を作成し、その上で await を呼び出します。これらの future は同時に存在します。

各ブロックには、await の前後にスレッド ID が表示されます。

出力:

Standard Output
Start the thread 1, id= ThreadId(2)
Start the thread 3, id= ThreadId(2)
Start the thread 4, id= ThreadId(2)
Start the thread 5, id= ThreadId(2)
Start the thread 2, id= ThreadId(3)
end the thread 2, id = ThreadId(2))
end the thread 3, id = ThreadId(3))
end the thread 1, id = ThreadId(3))
end the thread 4, id = ThreadId(3))
end the thread 5, id = ThreadId(3))