我有一个进程从 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
尝试克隆`self``
tokio::spawn(async move {
self.clone().do_more_stuff(tx).await.unwrap_or_else(|err| {
println!("ERROR: {err}");
});
});