How to use `async fn` in `thread::spawn`

Hello, I'm newbie in Rust and trying to do some multithreading stuff.

Long story short, here's what I'm trying to accomplish :

use std::sync::mpsc::channel;
use std::sync::mpsc::Sender;
use std::thread;

fn main() {
    let (tx, rx) = channel::<i32>();
    thread::spawn(move || stuff(tx));
    for val in rx {
        println!("{}", val);

async fn stuff(tx: Sender<i32>) {

But stuff() seems to never get executed. What am I missing ?
How do I execute a future async fn with thread::spawn ?


Don't mark your function as async :slight_smile:
In your case, you just want to execute a "normal" (synchronous) function on another thread.

By declaring stuff to be async you make it return a Future, which is the encapsulation of an asynchronous operation. You would need to give that to an executor to actually execute it. When compiling your code, Rust should also issue a warning that the Future created by stuff(tx) is unused. Edit: it does not.

Thanks for your fast answer !

It is a simplified version of what I'm trying to do, I made it async because the stuff function originally contained a call to async function reqwest::get("") and compiler required me for it to be encapsulated in async function.

Have good day

I managed to make it work by putting block_on in thread::spawn :

use futures::executor::block_on;
thread::spawn(move || block_on(stuff(tx)));

Is there a better way to do it or its the right way ?


1 Like

For now I would switch to reqwest::blocking::get which is a synchronous version of the function and avoid async until you know you want it.

Generally you don't want to be using block_on from futures. Use a real executor if you must use async code. In your case, you don't want async at all, so just use the blocking module.

1 Like

If you really want to use an async function better to use tokio
I guess this could be a minimal example

use tokio::runtime::Runtime;
use tokio::time::*;
fn main() {
    let mut rt = Runtime::new().unwrap();
    rt.block_on(async move {
        println!("hello from the async block");

        //bonus, you could spawn tasks too
        tokio::spawn(async { async_function("task1").await });
        tokio::spawn(async { async_function("task2").await });
    loop {}

async fn async_function(name: &str) {
    for i in 0..3 {
        println!("{} : {}", name, i);

This will print

hello from the async block
task0 : 0
task0 : 1
task0 : 2
task1 : 0
task2 : 0
task1 : 1
task2 : 1
task1 : 2
task2 : 2

Notice how you can await on an async function
additionally you can spawn a task to run simultaneously. See how task1 and task2 print together instead of one after another.


This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.