How to terminate or suspend a Rust thread from another thread?

后端 未结 3 1244
轮回少年
轮回少年 2020-12-08 16:14

Editor\'s note — this example was created before Rust 1.0 and the specific types have changed or been removed since then. The general questio

3条回答
  •  感动是毒
    2020-12-08 16:37

    Having been back to this question several times myself, here's what I think addresses OP's intent and others' best practice of getting the thread to stop itself. Building on the accepted answer, Crossbeam is a nice upgrade to mpsc in allowing message endpoints to be cloned and moved. It also has a convenient tick function. The real point here is it has try_recv() which is non-blocking.

    I'm not sure how universally useful it'd be to put a message checker in the middle of an operational loop like this. I haven't found that Actix (or previously Akka) could really stop a thread without--as stated above--getting the thread to do it itself. So this is what I'm using for now (wide open to correction here, still learning myself).

    // Cargo.toml:
    // [dependencies]
    // crossbeam-channel = "0.4.4"
    
    use crossbeam_channel::{Sender, Receiver, unbounded, tick};
    use std::time::{Duration, Instant};
    
    fn main() {
        let (tx, rx):(Sender, Receiver) = unbounded();
        let rx2 = rx.clone();
    
        // crossbeam allows clone and move of receiver
        std::thread::spawn(move || {
            // OP:
            // let mut timer = Timer::new().unwrap();
            // let periodic = timer.periodic(Duration::milliseconds(200));
    
            let ticker: Receiver = tick(std::time::Duration::from_millis(500));
    
            loop {
                // OP:
                // periodic.recv();
                crossbeam_channel::select! {
                    recv(ticker) -> _ => {
    
                        // OP: Do my work here
                        println!("Hello, work.");
    
                        // Comms Check: keep doing work?
                        // try_recv is non-blocking
                        // rx, the single consumer is clone-able in crossbeam
                        let try_result = rx2.try_recv();
                        match try_result {
                            Err(_e) => {},
                            Ok(msg) => {
                                match msg.as_str() {
                                    "END_THE_WORLD" => {
                                        println!("Ending the world.");
                                        break;
                                    },
                                    _ => {},
                                }
                            },
                            _ => {}
                        }
                    }
                }
            }
        });
    
        // let work continue for 10 seconds then tell that thread to end.
        std::thread::sleep(std::time::Duration::from_secs(10));
        println!("Goodbye, world.");
        tx.send("END_THE_WORLD".to_string());
    }
    

    Using strings as a message device is a tad cringeworthy--to me. Could do the other suspend and restart stuff there in an enum.

提交回复
热议问题