简体   繁体   中英

In Rust, what is gained from making a function 'async'?

I know that an async function will return a Future, and that calling .await on that future will repeatedly call poll() on it until it completes, but I don't understand the difference between that and a regular function. Does it give any benefit to make a function async if it already works without it?

I have two versions of code that do the same thing. Consider the "experiment" functions as main functions running with #[tokio::main] .

One version calls a regular function to create code that can run asynchronously with tokio::spawn() ( playground link , though it seems to not show the output well):

pub async fn experiment1() {
    spawn_task(1);
    spawn_task(2);

    loop {
        println!("3");
        tokio::time::sleep(Duration::from_secs(1)).await;
    }
    
}

fn spawn_task(n: i32) {
    tokio::spawn(async move {
       loop {
           println!("{n}");
           tokio::time::sleep(Duration::from_secs(1)).await;
       }
    });
}

The output of this is below (3 numbers print out every second, this is 3 seconds worth of output). Each loops runs concurrently.

3
1
2
3
2
1
3
1
2

The other version uses async and await ( playground link , though it seems to not show the output well):

pub async fn experiment3() {
    spawn_task(1).await;
    spawn_task(2).await;

    loop {
        println!("3");
        tokio::time::sleep(Duration::from_secs(1)).await;
    }
    
}

async fn spawn_task(n: i32) {
    tokio::spawn(async move {
       loop {
           println!("{n}");
           tokio::time::sleep(Duration::from_secs(1)).await;
       } 
    });
}

The output of this is below (3 numbers print out every second, this is 3 seconds worth of output). Each loops also runs concurrently.

3
1
2
3
1
2
3
2
1

When you only run synchronous code like in your examples the only difference is that you change the return type from plain T to impl Future<Output = T> . You might want to use this to use otherwise synchronous functions in places where an asynchronous function is expected.

The real benefit comes in when you actually use asynchronous code inside of it:

fn fun() {
    // this is not allowed because we're not inside an async block or function
    tokio::time::sleep(Duration::from_secs(1)).await;
}

The above function is not allowed, to make it work we have to declare it as an async function:

async fn fun() {
    // we can use await here
    tokio::time::sleep(Duration::from_secs(1)).await;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM