当你不能使主函数异步时如何在 Rust 中使用 async/await

我有一个下载异步文件的功能:

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");
    }
}

我想调用此函数来下载文件,然后在需要时等待它。
但问题是,如果我这样做,我会收到一个错误:

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

所以我必须使主函数异步,但是当我这样做时,我得到另一个错误:

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
}

那么我该如何使用 async 和 await
感谢您的帮助

stack overflow How to use async/await in Rust when you can't make main function async
原文答案
author avatar

接受的答案

最常用的运行时 tokio 提供了一个属性宏,以便您可以使您的主函数异步:

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

答案:

作者头像

一个已建立的模式是 here

从同步块中,构建一个新的运行时,然后在其上调用 block_on()

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

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

您不能以异步方式运行,因为必须有一个父线程来轮询主函数的结果。如果 main 本身是异步的,那么谁来轮询 main?异步函数的返回类型总是这样,impl future<output= Sometype + sometrait(if exists)> 。未来的 tarit 还提供 poll 方法,以便执行者知道何时继续。参见 rust asyn prog。在 rust 中要深入了解,您可以在 main 方法中调用 block_on(some async task),这将阻塞当前线程,即 main,直到给定的异步任务未完成,另一方面,await 不会阻塞当前线程.这就是为什么使用 .await 的函数首先必须是异步的

作者头像

您还可以使用 async-std 作为异步实现。

你的 Cargo.toml 应该有这个:

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

然后你可以像这样使用它:

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