Jestem początkującym rdzy i nie mogę uzyskać następującego kodu, aby skompilować. Wiem, że ten problem może nie być nowy, próbowałem przeszukiwać wszędzie, ale nie mogłem znaleźć odpowiedniej odpowiedzi na poniższy problem.

Zasadniczo próbuję wywołać metody z wątku, a także za pomocą różnych struktur do wysyłania i odbierania obiektów między niciami.

use std::{thread, time};

struct SenderStruct;

impl SenderStruct {
    fn send(&self, sndr: Sender<(Option<String>)>) {
        let count = 0;
        loop {
            sndr.send(Some(String::from("Hello"))).unwrap();
            thread::sleep(time::Duration::from_millis(1000));
            count = count + 1;

            if count == 50 {
                break;
            }
        }

        sndr.send(None);
    }
}

struct ReceiveStruct;

impl ReceiveStruct {
    fn receive(&self, rec: Receiver<Option<String>>) {
        loop {
            let recv_out = rec.recv().unwrap();
            match recv_out {
                Some(some_str) => println!("{}", some_str),
                None => break,
            }
        }
    }
}

struct SendReceiveStruct {
    m_ss: SenderStruct,
    m_sos: ReceiveStruct,
    m_recv_hndlr: Option<thread::JoinHandle<()>>,
}

impl SendReceiveStruct {
    fn new() -> Self {
        SendReceiveStruct {
            m_ss: SenderStruct {},
            m_sos: ReceiveStruct {},
            m_recv_hndlr: None,
        }
    }

    fn start(&mut self) {
        let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();

        thread::spawn(move || self.m_ss.send(tx));
        self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
    }

    fn wait_for_recevier(&mut self) {
        self.m_recv_hndlr.unwrap().join();
    }
}
fn main() {
    println!("Hello, world!");

    let mut ubs = SendReceiveStruct::new();
    ubs.start();

    ubs.wait_for_recevier();
}

Ale mam na całe życie

$ cargo build
   Compiling threads v0.1.0 (/root/learn-rust/threads)
error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> src/main.rs:55:23
   |
55 |         thread::spawn(move || self.m_ss.send(tx));
   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 52:5...
  --> src/main.rs:52:5
   |
52 | /     fn start(&mut self) {
53 | |         let (tx, rx): (Sender<(Option<String>)>, Receiver<Option<String>>) = channel();
54 | |
55 | |         thread::spawn(move || self.m_ss.send(tx));
56 | |         self.m_recv_hndlr = Some(thread::spawn(move || self.m_sos.receive(rx)));
57 | |     }
   | |_____^
   = note: ...so that the types are compatible:
           expected &mut SendReceiveStruct
              found &mut SendReceiveStruct
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `[closure@src/main.rs:55:23: 55:49 self:&mut SendReceiveStruct, tx:std::sync::mpsc::Sender<std::option::Option<std::string::String>>]` will meet its required lifetime bounds
  --> src/main.rs:55:9
   |
55 |         thread::spawn(move || self.m_ss.send(tx));

Jakieś wskazówki (lub inne odniesienia) naprawdę pomogłyby, a także inne możliwe podejścia do powyższego problemu?

0
Ronin Goda 31 grudzień 2019, 15:22

1 odpowiedź

Najlepsza odpowiedź

Jeśli zbadasz podpis std::thread::spawn :

pub fn spawn<F, T>(f: F) -> JoinHandle<T>
where
    F: FnOnce() -> T,
    F: Send + 'static,
    T: Send + 'static,

I jej dokumentacja ściśle:

Ograniczenie 'static oznacza, że zamknięcie i wartość powrotowa musi mieć żywotność całego wykonania programu. Powodem tego jest to, że wątki mogą odłączyć i przewidzieć żywotność, w których zostały utworzone.

Jednak zamknięcie wartości &mut self zamyka się nad może nie żyć wystarczająco długo. Jednym ze sposobów przezwyciężenia, że jest klonowanie wartości zamykania faktycznie używa:

#[derive(Clone)]
struct SenderStruct;

#[derive(Clone)]
struct ReceiveStruct;

impl SendReceiveStruct {
    fn start(&mut self) {
        let (tx, rx): (Sender<Option<String>>, Receiver<Option<String>>) = channel();

        thread::spawn({
            let ss = self.m_ss.clone();
            move || ss.send(tx)
        });
        self.m_recv_hndlr = Some(thread::spawn({
            let sos = self.m_sos.clone();
            move || sos.receive(rx)
        }));
    }

    fn wait_for_recevier(&mut self) {
        self.m_recv_hndlr.take().unwrap().join();
    }
}

Z wyjątkiem kilku innych drobnych problemów, Twój kod się teraz kompiluje.

3
edwardw 31 grudzień 2019, 12:59