Understanding `async`, `.await`, and `block_on()` in Rust (with Real Examples)
As a Rust systems programmer, you may often run into concepts like async, .await, and tokio::runtime::block_on(). These are essential tools for writing efficient, non-blocking applications—but they're also often misunderstood by beginners. In this blog post, we will break down: What async and .await do in Rust Why block_on() exists and when to use it How these differ from traditional synchronous (blocking) functions Real-world examples with code A comparison of blocking vs async behavior Multi-threading vs async in practical Rust usage Why Use async? Rust's async support enables you to write code that can perform long-running operations—like file I/O or HTTP requests—without blocking the entire thread. async fn say_hello() { println!("Hello from async!"); } To actually run this, you need to use .await inside an async context or call it using block_on() if you're in sync code: use tokio::runtime::Runtime; fn main() { let rt = Runtime::new().unwrap(); rt.block_on(say_hello()); } What Does block_on() Do? block_on() is a method that runs an async function from a synchronous context, like main(). It will: Start the async task Block the thread until the task completes This is especially useful in CLI applications or testing where you don't want your whole program to be async. Comparing Sync vs Async

As a Rust systems programmer, you may often run into concepts like async
, .await
, and tokio::runtime::block_on()
. These are essential tools for writing efficient, non-blocking applications—but they're also often misunderstood by beginners.
In this blog post, we will break down:
- What
async
and.await
do in Rust - Why
block_on()
exists and when to use it - How these differ from traditional synchronous (blocking) functions
- Real-world examples with code
- A comparison of blocking vs async behavior
- Multi-threading vs async in practical Rust usage
Why Use async
?
Rust's async
support enables you to write code that can perform long-running operations—like file I/O or HTTP requests—without blocking the entire thread.
async fn say_hello() {
println!("Hello from async!");
}
To actually run this, you need to use .await
inside an async context or call it using block_on()
if you're in sync code:
use tokio::runtime::Runtime;
fn main() {
let rt = Runtime::new().unwrap();
rt.block_on(say_hello());
}
What Does block_on()
Do?
block_on()
is a method that runs an async function from a synchronous context, like main()
. It will:
- Start the async task
- Block the thread until the task completes
This is especially useful in CLI applications or testing where you don't want your whole program to be async.