Use `async` to define a function, closure, or block that returns a future. The future is lazy: creating it does not run its body. Within an async context, `.await` drives a future toward its result and gives the runtime opportunities to schedule other tasks. This keeps asynchronous code close to synchronous control flow without requiring direct calls to `Future::poll`. section 8.4 section 8.11
Run an awaited timer
`#[tokio::main] async fn main() { tokio::time::sleep(std::time::Duration::from_secs(1)).await; println!("Hello, world!"); }` The macro starts a Tokio runtime and supplies the async context required by `.await`. Without a runtime driving the future, merely creating the sleep future would not run it. section 8.3.1 section 8.4
#[tokio::main]
async fn main() {
async {
println!("This line prints first");
}
.await;
let _future = async {
println!("This line never prints");
};
tokio::task::spawn(async {
println!(
"This line prints sometimes, depending on how quick it runs"
)
});
println!("This line always prints, but it may or may not be last");
}
Compare an awaited block, a future that is never awaited, and a spawned task. The unawaited block never prints; the spawned task may not print before the program exits. Spawning is not a completion guarantee—await its task handle when completion matters. section 8.4
Choose execution and concurrency deliberately:
- Use `.await` inside async code when the current task needs a future’s result. Use `tokio::task::spawn()` to schedule a task; await its handle if the caller must know it finished. section 8.4
- Use `tokio::select!` or `tokio::join!` for explicit concurrency, and `tokio::task::spawn_blocking()` for blocking operations rather than treating ordinary blocking work as async work. section 8.11
- Pick a runtime alongside the crates that depend on it. Rust supplies `Future`, `async`, and `.await`, but not a prescribed runtime; mixing runtimes in one context is impractical, and Tokio is the recommended default here. section 8.1
Trait-based APIs expose what the syntax normally hides. In the implementation snapshot shown here, an async observer method is expressed as a returned future; returning `Box<dyn Future<…>>` alone fails at `.await` because the trait object is not `Unpin`. Returning `Pin<Box<dyn Future<…>>>` and constructing it with `Box::pin(async { … })` addresses that error. The stated availability of async methods in traits is time-specific, not a timeless language limitation. section 8.6
In short: start a compatible runtime, await futures you need to execute, and distinguish a spawned task from one whose completion you have confirmed. section 8.1 section 8.4
















