await in Rust

Nilesh Katuwal 18 August 2022
await in Rust

In diesem Artikel lernen wir die Bedeutung von warten in Rust kennen.

await in Rust

async-await ist eine Technik zum Schreiben von Funktionen, die anhalten, die Kontrolle an die Laufzeit übergeben und dann die Ausführung dort fortsetzen können, wo sie aufgehört haben. Normalerweise werden diese Pausen verwendet, um auf E/A zu warten, aber sie können verschiedenen Zwecken dienen.

async-await ist Ihnen vielleicht von JavaScript oder C# bekannt. Die Implementierung der Funktionalität in Rust weist jedoch einige wichtige Änderungen auf.

Um async-await zu nutzen, müssen Sie fn durch async fn ersetzen:

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

Im Gegensatz zu einer herkömmlichen Funktion hat der Aufruf eines async fn keine unmittelbare Wirkung. Stattdessen gibt es eine future zurück.

Die Berechnung wird ausgesetzt und wartet darauf, ausgeführt zu werden. Verwenden Sie den .await-Operator, um das future auszuführen:

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

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

Dieses Beispiel verdeutlicht den ersten Unterschied zwischen Rust und anderen Sprachen: Wir schreiben future.await statt await future. Diese Syntax interagiert besser mit Rusts ? Operator zum Propagieren von Fehlern, die bei der E/A üblich sind.

Sie können future.await? schreiben. Fehler zu tragen und das Ergebnis von vielem abzuwarten. Zusätzlich hat es den Vorteil, dass die Methode des Verkettens schmerzlos wird.

Der Begriff await kann nur im Zusammenhang mit asynchronen Funktionen verwendet werden, und nur auf asynchrone Funktionen kann gewartet werden.

Rusts future sind lax; Standardmäßig werden sie nichts tun, bevor die erste Umfrage durchgeführt wird. Wenn man await die future, wird sie abgefragt.

Rufen Sie beispielsweise eine Funktion auf, die am Anfang Ihres Programms ein future zurückgibt, aber erst am Ende des Programms darauf await, wird die eigentliche Anfrage erst ausgeführt, wenn Sie darauf await.

Beispiel:

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

Zunächst werden fünf futures (fünf async-Blöcke) erstellt, wobei jede future eine sleep-Future erstellt und darauf await aufruft. Diese futures existieren gleichzeitig.

Jeder Block zeigt die Thread-ID vor und nach await an.

Ausgabe:

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))