La programmation asynchrone est un concept important dont vous devez être conscient en tant que développeur Rust.
Les modèles de programmation synchrone traditionnels entraînent souvent des goulots d'étranglement au niveau des performances. En effet, le programme attend la fin des opérations lentes avant de passer à la tâche suivante. Cela se traduit souvent par une mauvaise utilisation des ressources et une expérience utilisateur lente.
La programmation asynchrone vous permet d'écrire du code non bloquant qui utilise efficacement les ressources système. En tirant parti de la programmation asynchrone, vous pouvez concevoir des applications qui exécutent plusieurs tâches. La programmation asynchrone est pratique pour gérer plusieurs requêtes réseau ou traiter de grandes quantités de données sans bloquer le flux d'exécution.
Programmation asynchrone en Rust
Le modèle de programmation asynchrone de Rust vous permet de écrire du code Rust efficace qui s'exécute simultanément sans bloquer le flux d'exécution. La programmation asynchrone est avantageuse lorsqu'il s'agit d'opérations d'E/S, de demandes réseau et de tâches qui impliquent l'attente de ressources externes.
Vous pouvez implémenter la programmation asynchrone dans vos applications Rust de plusieurs manières. Ceux-ci incluent les fonctionnalités du langage, les bibliothèques et l'environnement d'exécution de Tokio.
Aussi, Le modèle de propriété de Rust et les primitives de simultanéité telles que les canaux et les verrous permettent une programmation simultanée sûre et efficace. Vous pouvez tirer parti de ces fonctionnalités avec la programmation asynchrone pour créer des systèmes simultanés qui évoluent bien et utilisent plusieurs cœurs de processeur.
Concepts de programmation asynchrone de Rust
Les contrats à terme fournissent une base pour la programmation asynchrone dans Rust. Un futur représente un calcul asynchrone qui n'a pas été complètement exécuté.
Les contrats à terme sont paresseux (ils ne sont exécutés que lorsqu'ils sont interrogés). Quand tu appelles un futur sondage() méthode, il vérifie si le futur est terminé ou nécessite des travaux supplémentaires. Si l'avenir n'est pas prêt, il revient Sondage:: En attente, indiquant que la tâche doit être planifiée pour une exécution ultérieure. Si l'avenir est prêt, il revient Sondage:: Prêt avec la valeur obtenue.
La chaîne d'outils standard de Rust comprend des primitives d'E/S asynchrones, une version asynchrone des E/S de fichiers, la mise en réseau et des minuteries. Ces primitives vous permettent d'effectuer des opérations d'E/S de manière asynchrone. Cela permet d'éviter de bloquer l'exécution d'un programme en attendant la fin des tâches d'E/S.
La syntaxe async/wait vous permet d'écrire du code asynchrone qui ressemble à du code synchrone. Cela rend votre code intuitif et facile à maintenir.
L'approche de Rust en matière de programmation asynchrone met l'accent sur la sécurité et les performances. Les règles de propriété et d'emprunt garantissent la sécurité de la mémoire et évitent les problèmes de simultanéité courants. La syntaxe Async/wait et les contrats à terme fournissent un moyen intuitif d'exprimer des workflows asynchrones. Vous pouvez utiliser un environnement d'exécution tiers pour gérer les tâches pour une exécution efficace.
Vous pouvez combiner ces fonctionnalités de langage, ces bibliothèques et cet environnement d'exécution pour écrire du code hautement performant. Il fournit un cadre puissant et ergonomique pour la construction de systèmes asynchrones. Cela fait de Rust un choix populaire pour les projets nécessitant une gestion efficace des tâches liées aux E/S et une simultanéité élevée.
Rust version 1.39 et les versions ultérieures ne prennent pas en charge les opérations asynchrones dans la bibliothèque standard de Rust. Vous aurez besoin d'une caisse tierce pour utiliser le asynchrone/attendre syntaxe pour gérer les opérations asynchrones dans Rust. Vous pouvez utiliser des packages tiers comme Tokyo ou asynchrone-std pour travailler avec la syntaxe async/wait.
Programmation asynchrone avec Tokio
Tokio est un environnement d'exécution asynchrone robuste pour Rust. Il fournit des fonctionnalités pour créer des applications hautement performantes et évolutives. Vous pouvez exploiter la puissance de la programmation asynchrone avec Tokio. Il fournit également des fonctionnalités d'extensibilité.
Au cœur de Tokio se trouve son modèle de planification et d'exécution de tâches asynchrones. Tokio vous permet d'écrire du code asynchrone avec la syntaxe async/wait. Cela permet une utilisation efficace des ressources système et une exécution simultanée des tâches. La boucle d'événements de Tokio gère efficacement la planification des tâches. Cela garantit une utilisation optimale des cœurs de processeur et minimise la surcharge de changement de contexte.
Les combinateurs de Tokio facilitent la coordination et la composition des tâches. Tokio fournit de puissants outils de coordination et de composition des tâches. Vous pouvez attendre que plusieurs tâches se terminent avec la jointure, sélectionner la première tâche terminée avec la sélection et faire la course les unes contre les autres avec la course.
Ajouter le Tokyo caisse à votre Cargaison.toml la section des dépendances du fichier.
[dependencies]
tokio = { version = "1.9", features = ["full"] }
Voici comment vous pouvez utiliser la syntaxe async/wait dans vos programmes Rust avec Tokio :
use tokio:: time:: sleep;
use std:: time:: Duration;asyncfnhello_world() {
println!("Hello, ");
sleep(Duration:: from_secs(1)).await;
println!("World!");
}
#[tokio:: main]
asyncfnmain() {
hello_world().await;
}
Le Bonjour le monde la fonction est asynchrone, elle peut donc utiliser le attendre mot-clé pour suspendre son exécution jusqu'à ce qu'un futur soit résolu. Le Bonjour le monde impression de fonction "Bonjour, " à la console. Le Durée:: from_secs (1) L'appel de fonction suspend l'exécution de la fonction pendant une seconde. Le attendre le mot-clé attend la fin du futur sommeil. Finalement, le Bonjour le monde impression de fonction "Monde!" à la console.
Le principal fonction est une fonction asynchrone avec le #[tokio:: main] attribut. Il désigne la fonction principale comme point d'entrée pour le runtime de Tokio. Le hello_world().wait exécute la fonction hello_world de manière asynchrone.
Retarder des tâches avec Tokio
Une tâche courante dans la programmation asynchrone utilise des retards ou des tâches de planification pour s'exécuter dans une plage de temps spécifiée. Le runtime tokio fournit un mécanisme pour utiliser des temporisateurs et des retards asynchrones à travers le tokio:: temps module.
Voici comment vous pouvez retarder une opération avec le runtime Tokio :
use std:: time:: Duration;
use tokio:: time:: sleep;asyncfndelayed_operation() {
println!("Performing delayed operation...");
sleep(Duration:: from_secs(2)).await;
println!("Delayed operation completed.");
}
#[tokio:: main]
asyncfnmain() {
println!("Starting...");
delayed_operation().await;
println!("Finished.");
}
Le opération_retardée fonction introduit un retard de deux secondes avec le dormir méthode. Le opération_retardée La fonction est asynchrone, elle peut donc utiliser await pour suspendre son exécution jusqu'à ce que le délai soit terminé.
Gestion des erreurs dans les programmes asynchrones
La gestion des erreurs dans le code Rust asynchrone implique l'utilisation de la Résultat taper et gestion des erreurs Rust avec le ? opérateur.
use tokio:: fs:: File;
use tokio:: io;
use tokio:: io::{AsyncReadExt};asyncfnread_file_contents() -> io::Result<String> {
letmut file = File:: open("file.txt").await?;
letmut contents = String::new();
file.read_to_string(&mut contents).await?;
Ok(contents)
}asyncfnprocess_file() -> io::Result {
let contents = read_file_contents().await?;
// Process the file contents
Ok(())
}
#[tokio:: main]
asyncfnmain() {
match process_file().await {
Ok(()) => println!("File processed successfully."),
Err(err) => eprintln!("Error processing file: {}", err),
}
}
Le lire_fichier_contenu la fonction renvoie un io:: Résultat qui représente la possibilité d'une erreur d'E/S. En utilisant le ? après chaque opération asynchrone, le runtime de Tokio propagera les erreurs vers le haut de la pile des appels.
Le principal La fonction gère le résultat avec un correspondre instruction qui imprime un texte basé sur le résultat de l'opération.
Reqwest utilise la programmation asynchrone pour les opérations HTTP
De nombreux crates populaires, y compris Reqwest, utilisent Tokio pour fournir des opérations HTTP asynchrones.
Vous pouvez utiliser Tokio avec Reqwest pour faire plusieurs requêtes HTTP sans bloquer d'autres tâches. Tokio peut vous aider à gérer des milliers de connexions simultanées et à gérer efficacement les ressources.