rust 如何在一个结构中存储一个JoinHandle,用于一个与自身一起运行的线程?

ebdffaop  于 2023-01-09  发布在  其他
关注(0)|答案(2)|浏览(130)

我需要创建一个线程并将线程连接句柄存储在结构体中,但是我得到了错误:

use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;

pub struct NetworkReceiver {
    terminate_flag: AtomicBool,
    join_handle: Option<thread::JoinHandle<()>>,
}

impl NetworkReceiver {
    pub fn new() -> NetworkReceiver {
        NetworkReceiver {
            terminate_flag: AtomicBool::new(false),
            join_handle: None,
        }
    }

    pub fn start(&mut self) {
        self.join_handle = Some(thread::spawn(|| self.run()));
    }

    pub fn run(&mut self) {
        while !self.terminate_flag.load(Ordering::Relaxed) {
            // ...
        }
    }

    pub fn terminate(&mut self) {
        self.terminate_flag.store(true, Ordering::Relaxed);
    }
}
error[E0506]: cannot assign to `self.join_handle` because it is borrowed
  --> src/main.rs:18:9
   |
18 |         self.join_handle = Some(thread::spawn(|| self.run()));
   |         ^^^^^^^^^^^^^^^^        ----------------------------
   |         |                       |             |  |
   |         |                       |             |  borrow occurs due to use in closure
   |         |                       |             borrow of `self.join_handle` occurs here
   |         |                       argument requires that `*self` is borrowed for `'static`
   |         assignment to borrowed `self.join_handle` occurs here

error[E0521]: borrowed data escapes outside of associated function
  --> src/main.rs:18:33
   |
17 |     pub fn start(&mut self) {
   |                  ---------
   |                  |
   |                  `self` is a reference that is only valid in the associated function body
   |                  let's call the lifetime of this reference `'1`
18 |         self.join_handle = Some(thread::spawn(|| self.run()));
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |                                 |
   |                                 `self` escapes the associated function body here
   |                                 argument requires that `'1` must outlive `'static`
htrmnn0y

htrmnn0y1#

您可以将join_handleNetworkReceiver中的其他内容分开,如下所示:

use std::thread;
use std::sync::{
    atomic::{AtomicBool, Ordering},
    Arc,
};

pub struct NetworkReceiver {
    terminate_flag: AtomicBool,
}
pub struct RunningNetworkReceiver {
    join_handle: thread::JoinHandle<()>,
    network_receiver: Arc<NetworkReceiver>,
}

impl NetworkReceiver {
    pub fn new() -> NetworkReceiver {
        let net_recv_intf = NetworkReceiver {
            terminate_flag: AtomicBool::new(false),
        };

        net_recv_intf
    }

    pub fn start(self) -> RunningNetworkReceiver {
        let network_receiver = Arc::new(self);
        let join_handle = {
            let network_receiver = network_receiver.clone();
            thread::spawn(move || network_receiver.run())
        };
        RunningNetworkReceiver {
            join_handle,
            network_receiver,
        }
    }
    pub fn run(&self) {
        while !self.terminate_flag.load(Ordering::Relaxed) {
        }
    }
}
impl RunningNetworkReceiver {
    pub fn terminate(&self) {
        self.network_receiver.terminate_flag.store(true, Ordering::Relaxed);
    }
}

如果你需要对NetworkReceiver内部的任何东西进行独占访问,那么你必须把它(或者需要它的部分) Package 在RwLockMutex或类似的东西中。

8ulbf1ek

8ulbf1ek2#

当在线程中使用变量时,该线程必须拥有所有权。(thread::spawn(|| self.run());这一行试图将self移入线程,但由于self需要比函数更长的寿命,因此无法移入。
我相信你必须将你的NetworkReceiver封装在一个Arc互斥体中。你可以改变你的NetworkReceiver::new()来返回一个Arc,并且所有相关的函数将从fn foo(&mut self)改变为fn foo(self: Arc<Self>)

相关问题