liveBook · Manning

Spawn_blocking

As explained in Code Like a Pro in Rust

tokio::task::spawn_blocking is a Tokio function that runs a blocking operation on a thread dedicated to blocking work.

tokio::task::spawn_blocking runs synchronous, potentially blocking code on Tokio’s dedicated blocking-thread queue and returns a future that can be awaited. It is the preferred bridge when an async context must call a crate without async support, such as a database driver or networking library. section 8.7

Read a file without blocking the async path

Write the file through tokio::fs, then move synchronous std::fs::read_to_string into spawn_blocking: tokio::task::spawn_blocking(|| read_file(filename)).await??. The returned future is awaited like ordinary async code, while the read executes on a Tokio-managed blocking thread. Tokio’s runtime builder can configure the number of blocking threads. section 8.7

use tokio::io::{self, AsyncWriteExt};
 
async fn write_file(filename: &str) -> io::Result<()> {                #1
    let mut f = tokio::fs::File::create(filename).await?;
    f.write(b"Hello, file!").await?;
    f.flush().await?;
 
    Ok(())
}
 
fn read_file(filename: &str) -> io::Result<String> {                   #2
    std::fs::read_to_string(filename)
}
 
#[tokio::main]
async fn main() -> io::Result<()> {
    let filename = "mixed-sync-async.txt";
    write_file(filename).await?;
 
    let contents =
        tokio::task::spawn_blocking(|| read_file(filename)).await??;   #3
 
    println!("File contents: {}", contents);
 
    tokio::fs::remove_file(filename).await?;
 
    Ok(())
}

Compare asynchronous file writing with synchronous reading delegated to spawn_blocking, including nested error propagation with .await??. section 8.7

How Code Like a Pro in Rust covers it

How deep it goes
Explains the returned future, Tokio’s blocking-thread queue, awaiting, and thread-count configuration without exposing implementation details.
Examples
Demonstrates asynchronous file writing followed by synchronous file reading and cleanup.
What it assumes
Assumes an async context and familiarity with futures and await while introducing the sync-to-async boundary.
What you can do after
Apply Tokio’s spawn_blocking API to run synchronous I/O from an async function and await its result.
How it connects
Connects blocking operations with async contexts, futures, await, Tokio tasks, and runtime configuration.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Code Like a Pro in Rust. The section links point to the parts of the book it draws on.