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

后端 未结 3 1237
轮回少年
轮回少年 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:50

    For both terminating and suspending a thread you can use channels.

    Terminated externally

    On each iteration of a worker loop, we check if someone notified us through a channel. If yes or if the other end of the channel has gone out of scope we break the loop.

    use std::io::{self, BufRead};
    use std::sync::mpsc::{self, TryRecvError};
    use std::thread;
    use std::time::Duration;
    
    fn main() {
        println!("Press enter to terminate the child thread");
        let (tx, rx) = mpsc::channel();
    
        thread::spawn(move || loop {
            println!("Working...");
            thread::sleep(Duration::from_millis(500));
            match rx.try_recv() {
                Ok(_) | Err(TryRecvError::Disconnected) => {
                    println!("Terminating.");
                    break;
                }
                Err(TryRecvError::Empty) => {}
            }
        });
    
        let mut line = String::new();
        let stdin = io::stdin();
        let _ = stdin.lock().read_line(&mut line);
    
        let _ = tx.send(());
    }
    

    Suspending and resuming

    We use recv() which suspends the thread until something arrives on the channel. In order to resume the thread, you need to send something through the channel; the unit value () in this case. If the transmitting end of the channel is dropped, recv() will return Err(()) - we use this to exit the loop.

    use std::io::{self, BufRead};
    use std::sync::mpsc;
    use std::thread;
    use std::time::Duration;
    
    fn main() {
        println!("Press enter to wake up the child thread");
        let (tx, rx) = mpsc::channel();
        thread::spawn(move || loop {
            println!("Suspending...");
            match rx.recv() {
                Ok(_) => {
                    println!("Working...");
                    thread::sleep(Duration::from_millis(500));
                }
                Err(_) => {
                    println!("Terminating.");
                    break;
                }
            }
        });
    
        let mut line = String::new();
        let stdin = io::stdin();
        for _ in 0..4 {
            let _ = stdin.lock().read_line(&mut line);
            let _ = tx.send(());
        }
    }
    

    Other tools

    Channels are the easiest and the most natural (IMO) way to do these tasks, but not the most efficient one. There are other concurrency primitives which you can find in the std::sync module. They belong to a lower level than channels but can be more efficient in particular tasks.

提交回复
热议问题