Programmation asynchrone en Rust : guide complet avec exemples

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Introduction à la programmation asynchrone en Rust



La programmation asynchrone est un paradigme qui permet d'effectuer des opérations d'entrée-sortie (requêtes réseau, lecture de fichiers, travail avec des bases de données) sans bloquer le thread d'exécution principal. En Rust, l'asynchronisme est implémenté via le système Future et les mots-clés async/await. Contrairement au multithreading, le code asynchrone s'exécute dans un seul thread, en basculant entre les tâches pendant l'attente.



Dans ce guide, nous aborderons :

  • Les bases de async/await en Rust
  • Le travail avec la crate tokio — le runtime asynchrone le plus populaire
  • La création et la combinaison de Future
  • Des exemples pratiques : un client HTTP asynchrone et des minuteurs


Cet article est destiné aux développeurs familiers avec la syntaxe de base de Rust. Si vous débutez, nous vous recommandons d'abord d'étudier les bases du langage sur PythonLib.



Bases de async/await et Future en Rust



Qu'est-ce qu'un Future ?



Future est un trait représentant une opération asynchrone qui peut se terminer dans le futur. En Rust, Future est paresseux : il ne fait rien tant qu'il n'est pas interrogé (poll). C'est le runtime asynchrone (par exemple, Tokio) qui est responsable de l'interrogation.



Un exemple simple de fonction asynchrone :



use std::time::Duration;

async fn say_hello() { println!("Bonjour du monde asynchrone !"); tokio::time::sleep(Duration::from_secs(1)).await; println!("1 seconde s'est écoulée");}

#[tokio::main]async fn main() { say_hello().await;}


Le mot-clé async transforme la fonction en un Future. L'appel .await suspend l'exécution de la tâche actuelle jusqu'à la fin du Future, sans bloquer le thread.



Cycle de vie d'une tâche asynchrone



Lorsque vous appelez .await, voici ce qui se passe :

  1. Le runtime interroge le Future (appelle la méthode poll())
  2. Si le Future est prêt — le résultat est retourné
  3. Si le Future attend (par exemple, une opération réseau) — le runtime bascule sur une autre tâche
  4. Lorsque la ressource devient disponible, le runtime reprend la tâche


Une particularité importante de Rust : .await ne peut être appelé qu'à l'intérieur d'une fonction asynchrone ou d'un bloc async {}. Tenter de l'utiliser dans un contexte synchrone entraînera une erreur de compilation.



Travail pratique avec Tokio



Installation et configuration



Tokio est un runtime asynchrone pour Rust, fournissant un planificateur de tâches, des minuteurs, des sockets réseau et bien plus encore. Pour commencer, ajoutez dans Cargo.toml :



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


Le flag features = ["full"] active toutes les fonctionnalités de Tokio. Pour la production, il est préférable de ne sélectionner que les fonctionnalités nécessaires.



Lancement de plusieurs tâches asynchrones



L'un des principaux avantages de l'asynchronisme est l'exécution parallèle de multiples tâches. Utilisez tokio::spawn pour lancer des tâches en arrière-plan :



use tokio::time::{sleep, Duration};

async fn task(name: &str, seconds: u64) { println!("Tâche {} a commencé", name); sleep(Duration::from_secs(seconds)).await; println!("Tâche {} terminée après {} sec", name, seconds);}

#[tokio::main]async fn main() { let handle1 = tokio::spawn(task("A", 2)); let handle2 = tokio::spawn(task("B", 1));

// Attend la fin des deux tâches let _ = tokio::join!(handle1, handle2); println!("Toutes les tâches sont terminées");}


La macro tokio::join! attend la fin de tous les Future passés. Si une tâche se termine plus tôt, l'exécution n'est pas interrompue — nous attendons les autres.



Gestion des erreurs dans le code asynchrone

Blogs

Book Recommendations