2

我正在学习 Rust,尤其是并行的多线程和异步请求。

我阅读了文档,但我仍然不明白我在哪里犯了错误。我假设我知道在哪里,但不知道如何解决它。

main.rs

use std::thread;

struct Request {
    url: String,
}

impl Request {
    fn new(name: &str) -> Request {
        Request {
            url: name.to_string(),
        }
    }

    async fn call(&self, x: &str) -> Result<(), Box<dyn std::error::Error>> {
        let resp = reqwest::get(x).await;
        Ok(())
    }
}

#[tokio::main]
async fn main() {
    let requests = vec![
        Request::new("https://www.google.com/"),
        Request::new("https://www.google.com/"),
    ];
    let handles: Vec<_> = requests
        .into_iter()
        .map(|request| {
            thread::spawn(move || async {
                request.call(&request.url).await;
            })
        })
        .collect();

    for y in handles {
        println!("{:?}", y);
    }
}
error[E0515]: cannot return value referencing local data `request`
  --> src/main.rs:29:35
   |
29 |               thread::spawn(move || async {
   |  ___________________________________^
30 | |                 request.call(&request.url).await;
   | |                 ------- `request` is borrowed here
31 | |             })
   | |_____________^ returns a value referencing data owned by the current function

货运.toml

[dependencies]
reqwest = "0.10.4"
tokio = { version = "0.2", features = ["full"] }
4

1 回答 1

4

像闭包一样,async块尽可能弱地捕获它们的变量。按优先顺序:

  1. 不可变引用
  2. 可变引用
  3. 按价值

这取决于变量在闭包/异步块中的使用方式。在您的示例中,request仅通过引用使用,因此仅通过引用捕获:

async {
    request.call(&request.url).await;
}

但是,您需要将变量的所有权转移到异步块,以便在最终执行未来时变量仍然存在。像闭包一样,这是通过move关键字完成的:

thread::spawn(move || async move {
    request.call(&request.url).await;
})

也可以看看:


在您理解的这一点上,您不太可能想要混合线程和异步。一个本质上是阻塞的,另一个期望代码不会阻塞。您应该按照如何使用 reqwest 执行并行异步 HTTP GET 请求中概述的示例进行操作?反而。

也可以看看:

于 2020-03-30T19:51:59.040 回答