在 Arc 包装方法中使用结构体字段值会给出“发生移动是因为 self 的类型为 Arc<T>,它不实现复制”

问题描述 投票:0回答:1

我有一个进程从 tokio

oneshot::channel
接收数据,然后将其与一些
self
结构字段结合使用,但是,即使将其包装在
Arc
中,我对结构字段的访问似乎也是不允许的。试图了解如何成功实现这一目标:

use anyhow::{Error, Result};
use std::sync::Arc;
use tokio::time::{sleep, Duration};
use tokio::sync::oneshot::{self, Sender, Receiver};
use rand::Rng;

#[derive(Debug)]
pub struct Task {
    some_data: String,
    some_other_data: String,
}

impl Task {
    pub fn new(some_data: String, some_other_data: String) -> Self {
        Self {some_data, some_other_data} 
    }

    pub async fn do_stuff(self: Arc<Task>) -> Result<(), Error> {

        // spawn task with a self method
        let (tx, rx): (Sender<String>, Receiver<String>) = oneshot::channel();
        tokio::spawn(async move {
            self.do_more_stuff(tx).await.unwrap_or_else(|err| {
                println!("ERROR: {err}");
            });
        });

        match rx.await {
            Ok(data) => {
                // using self fields here results in error
                println!("{}, {} took: {}", self.some_data.clone(), self.some_other_data.clone(), data)
            }
            Err(_) => {
                panic!();
            }
        }
        Ok(())
    }

    pub async fn do_more_stuff(self: Arc<Task>, tx: Sender<String>) -> Result<(), Error> {

        let sleep_time = rand::thread_rng().gen_range(0..3);
        sleep(Duration::from_secs(sleep_time)).await;


        // send on channel
        if let Err(_) = tx.send(sleep_time.to_string()) {
            panic!();
        }
        Ok(())
    }
}

#[tokio::main]
async fn main() -> Result<(), Error> {

    let data_one = String::from("hello");
    let data_two = String::from("world");

    // spawn some tasks
    let mut handles = Vec::new();
    for _ in 0..5 {
        let t = Arc::new(Task::new(data_one.clone(), data_two.clone()));
        handles.push(
            tokio::spawn(async move { t.do_stuff().await })
        );
    }

    futures::future::join_all(handles).await;
    Ok(())
}

货物.Toml

[dependencies]
anyhow = "1.0.82"
tokio = { version = "1", features = ["full"] }
futures = "0.3.30"
rand = "0.8"

[dependencies.tokio-util]
version = "0.6"
features = ["compat"]

编辑:添加编译器错误:

(main) bash > cargo check
    Checking arc_testing v0.1.0 (C:\Users\me\rust_sandbox\arc_testing)
error[E0382]: borrow of moved value: `self`
    --> src\main.rs:30:45
     |
18   |       pub async fn do_stuff(self: Arc<Task>) -> Result<(), Error> {
     |                             ---- move occurs because `self` has type `Arc<Task>`, which does not implement the `Copy` trait
...
22   |           tokio::spawn(async move {
     |  ______________________-
23   | |             self.do_more_stuff(tx).await.unwrap_or_else(|err| {
     | |             ---- variable moved due to use in coroutine
24   | |                 println!("ERROR: {err}");
25   | |             });
26   | |         });
     | |_________- value moved here
...
30   |                   println!("{}, {} took: {}", self.some_data.clone(), self.some_other_data.clone(), data)
     |                                               ^^^^^^^^^^^^^^ value borrowed here after move
     |
     = note: borrow occurs due to deref coercion to `Task`
note: deref defined here
    --> C:\Users\me\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib/rustlib/src/rust\library\alloc\src\sync.rs:2054:5
     |
2054 |     type Target = T;
     |     ^^^^^^^^^^^
help: clone the value to increment its reference count
     |
26   |         }.clone());
     |          ++++++++

For more information about this error, try `rustc --explain E0382`.
error: could not compile `arc_testing` (bin "arc_testing") due to 1 previous error
rust async-await rust-tokio
1个回答
0
投票

尝试克隆`self``

tokio::spawn(async move {
   self.clone().do_more_stuff(tx).await.unwrap_or_else(|err| {
      println!("ERROR: {err}");
   });
});
© www.soinside.com 2019 - 2024. All rights reserved.