代码之家  ›  专栏  ›  技术社区  ›  Nika

如何在一个线程中变异自我[[副本]

  •  1
  • Nika  · 技术社区  · 7 年前

    我创建了一个简单的例子来重现我的问题。 tx_thread rx_thread 寻找信息;当有任何可用的东西时,它会处理,并且还应该改变结构的当前状态。

    use std::sync::mpsc;
    use std::thread;
    use std::time::Duration;
    
    // this will also implement Drop trait to wait threads to
    // be finished (message will be Enum instead of number in this case)
    
    #[derive(Debug)]
    struct MyStruct {
        num: u32,
        tx_thread: Option<thread::JoinHandle<()>>,
        rx_thread: Option<thread::JoinHandle<()>>,
    }
    
    impl MyStruct {
        fn new() -> MyStruct {
            MyStruct {
                num: 0,
                tx_thread: None,
                rx_thread: None,
            }
        }
    
        fn start(&mut self) {
            let (tx, rx) = mpsc::channel();
    
            // tx thread will read from serial port infinitely,
            // and send data to mpsc channel after certain condition
            // to be processed.
            let tx_thread = thread::spawn(move || {
                let mut i = 0;
    
                loop {
                    tx.send(i).unwrap();
                    i += 1;
                    thread::sleep(Duration::from_secs(1));
                }
            });
    
            // after this will receive message, it will start
            // processing and mutate `self` state if needed.
            let rx_thread = thread::spawn(move || loop {
                let num = rx.recv().unwrap();
                println!("{:?}", num);
    
                /* here, how do I save `num` to `self`? */
    
                thread::sleep(Duration::from_secs(1));
            });
    
            self.tx_thread = Some(tx_thread);
            self.rx_thread = Some(rx_thread);
        }
    }
    
    fn main() {
        let mut s = MyStruct::new();
        s.start();
        thread::sleep(Duration::from_secs(999999));
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Nika    7 年前

    一个在discord频道的了不起的家伙(坏笔)告诉我这个非常好的解决方案,所有的功劳都归功于他。

    Arc<Mutex<>>

    use std::sync::{mpsc, Arc, Mutex};
    use std::thread;
    use std::time::Duration;
    
    type MyType = Arc<Mutex<u32>>;
    
    #[derive(Debug)]
    struct MyStruct {
        num: MyType,
        tx_thread: Option<thread::JoinHandle<()>>,
        rx_thread: Option<thread::JoinHandle<()>>,
    }
    
    impl MyStruct {
        fn new() -> MyStruct {
            MyStruct {
                num: Arc::new(Mutex::new(0)),
                tx_thread: None,
                rx_thread: None,
            }
        }
    
        fn start(&mut self) {
            let (tx, rx) = mpsc::channel();
    
            // tx thread will read from serial port infinitely,
            // and send data to mpsc channel after certain condition
            // to be processed.
            let tx_thread = thread::spawn(move || {
                let mut i = 0;
    
                loop {
                    tx.send(i).unwrap();
                    i += 1;
                    thread::sleep(Duration::from_secs(1));
                }
            });
    
            // clone here.
            let arc_num = self.num.clone();
            let rx_thread = thread::spawn(move || loop {
                let num = rx.recv().unwrap();
                // println!("{:?}", num);
    
                // now we can use it for writing/reading.
                *arc_num.lock().unwrap() = num;
                println!("{:?}", *arc_num.lock().unwrap());
    
                thread::sleep(Duration::from_secs(1));
            });
    
            self.tx_thread = Some(tx_thread);
            self.rx_thread = Some(rx_thread);
        }
    }
    
    fn main() {
        let mut s = MyStruct::new();
        s.start();
        thread::sleep(Duration::from_secs(999999));
    }
    

    编辑:另一种解决方案是使用 弧<互斥(<&燃气轮机&燃气轮机; 在那里工作,这样你就可以得到你需要的一切。

    参见下面的代码:

    use std::default::Default;
    use std::sync::{mpsc, Arc, Mutex};
    use std::thread;
    use std::time::Duration;
    
    // this will also implement Drop trait to wait threads to
    // be finished (message will be Enum instead of number in this case)
    
    #[derive(Debug, Default)]
    struct MyStructInner {
        num: u32,
        tx_thread: Option<thread::JoinHandle<()>>,
        rx_thread: Option<thread::JoinHandle<()>>,
    }
    
    #[derive(Debug, Default)]
    struct MyStruct {
        inner: Arc<Mutex<MyStructInner>>,
    }
    
    impl MyStruct {
        fn new() -> MyStruct {
            MyStruct {
                inner: Arc::new(Mutex::new(MyStructInner {
                    num: 0,
                    ..Default::default()
                })),
            }
        }
    
        fn start(&mut self) {
            let (tx, rx) = mpsc::channel();
    
            // tx thread will read from serial port infinitely,
            // and send data to mpsc channel after certain condition
            // to be processed.
            let tx_thread = thread::spawn(move || {
                let mut i = 0;
    
                loop {
                    tx.send(i).unwrap();
                    i += 1;
                    thread::sleep(Duration::from_secs(1));
                }
            });
    
            // after this will receive message, it will start
            // processing and mutate `self` state if needed.
            let local_self = self.inner.clone();
            let rx_thread = thread::spawn(move || loop {
                let num = rx.recv().unwrap();
    
                local_self.lock().unwrap().num = num;
                println!("{:?}", local_self.lock().unwrap().num);
    
                thread::sleep(Duration::from_secs(1));
            });
    
            self.inner.lock().unwrap().tx_thread = Some(tx_thread);
            self.inner.lock().unwrap().rx_thread = Some(rx_thread);
        }
    }
    
    fn main() {
        let mut s = MyStruct::new();
        s.start();
        thread::sleep(Duration::from_secs(999999));
    }
    
    推荐文章