如何在Rust结构体中存储线程连接句柄

wf82jlnq  于 2022-12-04  发布在  其他
关注(0)|答案(3)|浏览(126)

我需要通过在网络接收器结构体中存储线程连接句柄来创建网络接收器线程。但是当我在start方法中创建线程时,我得到了错误error[E0506]: cannot assign to self.join_handle because it is borrowederror[E0521]: borrowed data escapes outside of associated function。这是我的代码

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

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

impl NetworkReceiver {

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

        net_recv_intf
    }

    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);
    }
}
q5lcpyga

q5lcpyga1#

可以将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或类似的东西里。

w6lpcovy

w6lpcovy2#

当在线程中使用变量时,该线程必须拥有所有权。这一行(thread::spawn(|| self.run());试图将self移动到线程中,但不能,因为self需要比函数更长。
我相信你必须将NetworkReceiver Package 在Arc Mutex中。你可以将NetworkReceiver::new()更改为返回Arc,所有相关函数将从fn foo(&mut self)更改为fn foo(self: Arc<Self>)

t98cgbkg

t98cgbkg3#

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

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

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

        net_recv_intf
    }

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

    fn run(&self) {
        let mut buff: [u8; 2048] = [0; 2048];

        while !self.terminate_flag.load(Ordering::Relaxed) {
            // Do something here
        }
    }

    pub fn terminate(&mut self) {
        self.terminate_flag.store(true, Ordering::Relaxed);
    }
}

fn main() {
    let mut net_recv = NetworkReceiver::new();
    net_recv.start();
    net_recv.terminate();
}

我对您提供的代码做了一些更改:
我添加了一个main函数,它创建了一个NetworkReceiver的示例,并在该示例上调用start()和terminate()方法。我将run()方法设置为私有方法,因为它只能由start()方法调用。我将run()方法设置为引用自身而不是可变引用,因为它不会修改NetworkReceiver示例。

相关问题