Asynchrone Programmierung in Rust: Vollständiger Leitfaden für Anfänger

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Einführung in die asynchrone Programmierung in Rust



Asynchrone Programmierung ist ein Ansatz, der es Ihrer Anwendung ermöglicht, mehrere Aufgaben effizient gleichzeitig auszuführen, ohne den Hauptausführungsthread zu blockieren. In Rust wird dieser Ansatz durch das async/await-Modell implementiert, das die für die Sprache charakteristische Speichersicherheit und hohe Leistung bietet.



Im Gegensatz zur traditionellen Multithreading läuft asynchroner Code innerhalb eines oder mehrerer Threads und wechselt während Wartezeiten (z. B. I/O- oder Netzwerkanfragen) zwischen Aufgaben. Dies macht ihn ideal für die Erstellung von Hochleistungs-Webservern, Netzwerkanwendungen und Datenverarbeitungstools.



In diesem Artikel werden wir die Grundlagen der asynchronen Programmierung in Rust aufschlüsseln: von den wichtigsten Konzepten bis hin zu praktischen Beispielen. Sie erfahren, wie Future, async und await funktionieren, lernen die beliebte Laufzeitumgebung Tokio kennen und schreiben Ihr erstes asynchrones Projekt.



Grundlegende Konzepte: Future, async und await



Was ist ein Future?



In Rust wird eine asynchrone Aufgabe durch das Future-Trait repräsentiert. Ein Future ist ein Wert, der möglicherweise noch nicht bereit ist, aber in Zukunft verfügbar sein wird. Jeder Future hat eine poll-Methode, die überprüft, ob die Aufgabe abgeschlossen ist. Wenn die Aufgabe noch läuft, gibt sie Pending zurück; wenn sie abgeschlossen ist, gibt sie Ready(value) zurück.



Ein Future allein führt keine Arbeit aus. Er beschreibt nur, was passieren soll. Um asynchronen Code auszuführen, benötigen Sie eine Laufzeitumgebung — einen Executor, der Futures abfragt und deren Ausführung verwaltet.



Die Schlüsselwörter async und await



Das Schlüsselwort async verwandelt eine reguläre Funktion in eine asynchrone Funktion, die einen Future zurückgibt. Zum Beispiel:



async fn hello() -> String {    "Hallo, Welt!".to_string()}


Um das Ergebnis von einem Future zu erhalten, verwenden Sie .await. Es unterbricht die Ausführung der aktuellen Funktion, bis der Future abgeschlossen ist:



let result = hello().await;println!("{}", result);


Wichtig: .await kann nur innerhalb einer asynchronen Funktion oder eines async {}-Blocks verwendet werden.



Lebenszyklus einer asynchronen Aufgabe



  • Erstellung eines Futures (Aufruf einer asynchronen Funktion).
  • Übergabe des Futures an die Laufzeitumgebung zur Ausführung.
  • Die Laufzeitumgebung fragt den Future über poll ab.
  • Wenn die Aufgabe blockiert (wartet auf I/O), wechselt die Laufzeitumgebung zu einer anderen Aufgabe.
  • Wenn das Ergebnis bereit ist, gibt der Future Ready zurück.


Das Ökosystem: Tokio und async-std



Um mit asynchronem Code in Rust zu arbeiten, werden asynchrone Laufzeitumgebungen verwendet. Die beiden bekanntesten sind Tokio und async-std.



Tokio



Tokio ist der Industriestandard für asynchrone Programmierung in Rust. Es bietet einen multithreadfähigen Scheduler, asynchrone I/O, Timer, Synchronisation und Netzwerkprotokolle. Die meisten großen Projekte (z. B. Hyper, Tonic, Axum) basieren auf Tokio.



Um mit Tokio zu beginnen, fügen Sie die Abhängigkeit zu Cargo.toml hinzu:



[dependencies]tokio = { version = "1", features = ["full"] }


Das Hauptmakro zum Ausführen von asynchronem Code ist #[tokio::main]:



#[tokio::main]async fn main() {    println!("Hallo von Tokio!");}


async-std



async-std ist eine alternative Laufzeitumgebung, die bestrebt ist, der Rust-Standardbibliothek so ähnlich wie möglich zu sein. Sie ist einfacher für Anfänger, aber in der Produktion weniger beliebt.



Beispiel

Blogs

Buchempfehlungen