31

I have a function to download a file which is async:

async fn download_file() {
    fn main() {
        let resp = reqwest::blocking::get("https://sh.rustup.rs").expect("request failed");
        let body = resp.text().expect("body invalid");
        let mut out = File::create("rustup-init.sh").expect("failed to create file");
        io::copy(&mut body.as_bytes(), &mut out).expect("failed to copy content");
    }
}

I want to call this function to download a file and then await it when I need it.
But the problem is if I do it like this, I get an error:

fn main() {
    let download = download_file();
    // Do some work
    download.await; // `await` is only allowed inside `async` functions and blocks\nonly allowed inside `async` functions and blocks
    // Do some work
}

So I have to make the main function async, but when I do that I get another error:

async fn main() { // `main` function is not allowed to be `async`\n`main` function is not allowed to be `async`"
    let download = download_file();
    // Do some work
    download.await;
    // Do some work
}

So how can I use async and await
Thanks for helping

1

5 Answers 5

37

The most commonly used runtime, tokio, provides an attribute macro so that you can make your main function async:

#[tokio::main]
async fn main() {
    let download = download_file().await;
}

In case you don't have a dependency on tokio just yet, add the following to your Cargo.toml:

tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
Sign up to request clarification or add additional context in comments.

2 Comments

as of 10/18/22, Cargo.toml statement for tokio is tokio = { version = "1.21.2", features = ["full"] }, not tokio = "1.21.2"
@JohnMiller you don't need full, just runtime and macro features are enough
9

An established pattern for this is here.

From a synchronous block, build a new runtime then call block_on() on it:

let rt = tokio::runtime::Builder::new_current_thread()
        .enable_all()
        .build()
        .unwrap();

let res = rt.block_on(async { something_async(&args).await });

Comments

7

You can also use async-std as your async implementation.

Your Cargo.toml should have this:

[dependencies]
async-std = {version = "1.12.0", features = ["attributes"]}

And then you can use it like this:

#[async_std::main]
async fn main() {
 ....
}

Comments

6

you can not make run as async because there must be a parent thread which is going to poll the result of main function. if main is itself is async then who is going to poll main? the return type of a async function is always something like this, impl future<output= Sometype + sometrait(if exist)> . the future tarit also provide the poll method so that the executor may know when to proceed . See rust asyn prog. in rust to understand more in dept, you can call block_on(some async task) in main method, which will block the current thread ie main until the given async task is not finished, on the other hand , await does not block the current thread. which is why a function which use .await must be async at first place

1 Comment

While this is true, it doesn't answer OP's (simple) question of just wanting to know how to actually run their async code, and @msrd0's answer shows the simpest usecase >95% of async Rust users will be happy with.
1

Run async function into non async with tokio::runtime:

use tokio::runtime::Runtime;

async fn async_bar() -> String {
    println!("run async bar");
    String::from("return async bar")
}

fn non_async_foo() {
    let rt = Runtime::new().unwrap();
    
    let future = async_bar();
    let r = rt.block_on(future);
    
    println!("{r}");
}

fn main() {
    non_async_foo();
}

This example working for me with tokio features = ["full"]

Or better way use futures::executor see https://stackoverflow.com/a/74624227/8111346

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.