微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Actix:将共享数据移动到多个线程中的正确方法是什么?

如何解决Actix:将共享数据移动到多个线程中的正确方法是什么?

我有一个 config 结构,我在我的 actix 应用程序中共享它,如下所示:

pub fn run(addr: &str,pg_pool: PgPool,config: Settings) -> Result<Server,std::io::Error> {
    let pool = web::Data::new(pg_pool); 
    let arc_config = web::Data::new(Arc::new(config)); // <---

    let server = HttpServer::new(move || {
        App::new()
            .service(exhaust)
            .app_data(pool.clone())
            .app_data(arc_config.clone()) // <---
    })
    .bind(addr)?
    .run();

然后我有一个处理程序试图生成多个线程并将该 config 结构传递给每个线程:

#[get("/exhaust")]
pub async fn exhaust(pool: web::Data<PgPool>,config: web::Data<Arc<Settings>>) -> impl Responder {
    for _ in 1..16 {
        let handle = thread::spawn(move || {
            let inner_config = Arc::clone(&config);
            get_single_tweet(inner_config.as_ref().deref(),"1401287393228038149");
        });
    }

    HttpResponse::Ok()
}

我的想法是,因为 config 已经包含在 Arc() 中,所以我应该能够在每个线程中Arc::clone() 它,然后将其解引用到基础变量中。

但我收到此错误

error[E0382]: use of moved value: `config`
  --> src/twitter/routes/pull.rs:63:36
   |
58 | pub async fn exhaust(pool: web::Data<PgPool>,config: web::Data<Arc<Settings>>) -> impl Responder {
   |                                               ------ move occurs because `config` has type `actix_web::web::Data<Arc<Settings>>`,which does not implement the `copy` trait
...
63 |         let handle = thread::spawn(move || {
   |                                    ^^^^^^^ value moved into closure here,in prevIoUs iteration of loop
64 |             let inner_config = Arc::clone(&config);
   |                                            ------ use occurs due to use in closure

我正在努力理解为什么这会失败。如果配置在 Arc 内,那么为什么编译器认为我试图移动它而不是增加引用计数?

我还尝试了许多其他方法,但都没有成功:

  • 删除闭包前的 move - 编译器抱怨借用的值活得不够长
  • 取消引用 config 并将其包装在新的 Arc() 中 - 与原始错误类似

这样做的正确方法是什么?

解决方法

您需要在移动它之前克隆它。否则,您的第一次迭代必然需要采用它(因为不能保证 config 在任务运行时仍然存在以进行克隆)。然后你会得到你在第二次迭代中看到的错误,因为它也必然需要移动 config;这就是“在循环的前一次迭代中,这里的值移动到闭包中”的意思。

#[get("/exhaust")]
pub async fn exhaust(pool: web::Data<PgPool>,config: web::Data<Arc<Settings>>) -> impl Responder {
    for _ in 1..16 {
        let handle = thread::spawn({
            // Clone this here,so the closure gets its very own to move-capture.
            let inner_config = config.get_ref().clone();
            move || {
                get_single_tweet(inner_config.as_ref().deref(),"1401287393228038149");
            });
        }
    }

    HttpResponse::Ok()
}

请注意,web::Data 本身已经是 just a wrapper around Arc,因此您对嵌套的 Arc 有一些冗余。您可能只想:

#[get("/exhaust")]
pub async fn exhaust(pool: web::Data<PgPool>,config: web::Data<Settings>) -> impl Responder {
    for _ in 1..16 {
        let handle = thread::spawn({
            let inner_config = config.clone();
            move || {
                get_single_tweet(inner_config.as_ref().deref(),"1401287393228038149");
            });
        }
    }

    HttpResponse::Ok()
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?