Rust Async Programming Cheat Sheet
Covers async/await syntax, Futures, the Tokio runtime, spawning tasks, and common concurrency primitives for asynchronous Rust code.
3 PagesAdvancedApr 5, 2026
async/await Basics
Declaring and awaiting async functions.
rust
// An async fn returns a value that implements Future<Output = T>async fn fetch_data() -> String { String::from("data")}async fn run() { let data = fetch_data().await; // .await suspends until the future resolves println!("{}", data);}// Futures do nothing until polled/awaited or spawned on a runtime
The Tokio Runtime
Rust has no built-in async runtime; Tokio is the most widely used.
rust
// Cargo.toml: tokio = { version = "1", features = ["full"] }#[tokio::main]async fn main() { let result = fetch_data().await; println!("{}", result);}// Equivalent, without the macro:fn main() { let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { let result = fetch_data().await; println!("{}", result); });}
Spawning Tasks
Running futures concurrently on the runtime's thread pool.
rust
use tokio::task;#[tokio::main]async fn main() { let handle = task::spawn(async { // runs concurrently on the Tokio thread pool expensive_computation().await }); // do other work concurrently here... let result = handle.await.unwrap(); // join the task, propagate panics println!("{}", result);}async fn expensive_computation() -> u32 { 42}
Core Async Concepts
Vocabulary for reasoning about async Rust.
- Future- A trait representing a value that may not be ready yet; polled by an executor
- Executor/runtime- Drives futures to completion (e.g. Tokio, async-std); Rust has no built-in runtime
- .await- Suspends the current async fn until the future resolves, yielding control back to the executor
- async block- `async { ... }` creates an anonymous future without a named function
- Send + 'static- Requirements for futures spawned onto a multi-threaded runtime
- Pinning (Pin<Box<...>>)- Needed because async blocks can be self-referential and must not move once polled
Async Sync Primitives
Channels, mutexes, and combinators for coordinating async tasks.
rust
use tokio::sync::{Mutex, mpsc};use tokio::time::{sleep, Duration};#[tokio::main]async fn main() { // tokio::sync::Mutex is async-aware (lock().await, not blocking) let data = std::sync::Arc::new(Mutex::new(0)); // mpsc channel for async message passing let (tx, mut rx) = mpsc::channel::<i32>(32); tokio::spawn(async move { tx.send(10).await.unwrap(); }); let val = rx.recv().await; // join! runs multiple futures concurrently on the same task let (_a, _b) = tokio::join!(sleep(Duration::from_millis(10)), sleep(Duration::from_millis(20))); // select! races futures, taking the first to complete tokio::select! { _ = sleep(Duration::from_secs(1)) => println!("timeout"), v = rx.recv() => println!("got {:?}", v), }}
Pro Tip
Never call a blocking, CPU-heavy, or synchronous I/O function directly inside an async fn — it stalls the executor thread and starves other tasks. Use `tokio::task::spawn_blocking` to offload blocking work to a dedicated thread pool.
Was this cheat sheet helpful?
Explore Topics
#RustAsyncProgramming#RustAsyncProgrammingCheatSheet#Programming#Advanced#AsyncAwaitBasics#TheTokioRuntime#SpawningTasks#CoreAsyncConcepts#Concurrency#CheatSheet#SkillVeris
Advertisement
Sri Hayavadhana Info-Tech
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance