Edit: aggiornato per Rust 1.x
Per entrambi questi compiti (terminare e sospendere un filo) è possibile utilizzare i canali.
Ecco come un filo potrebbe essere chiuso esternamente:
use std::thread;
use std::time::Duration;
use std::sync::mpsc::{self, TryRecvError};
use std::io::{self, BufRead};
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(());
}
Cioè, ad ogni iterazione di un ciclo lavoratore che controllare se qualcuno ci ha comunicato attraverso un canale. Se sì o se l'altra estremità del canale è uscita dal campo di applicazione, interrompiamo il ciclo.
Ecco come un filo potrebbe essere "sospeso" e "riprese":
use std::time::Duration;
use std::thread;
use std::sync::mpsc;
use std::io::{self, BufRead};
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(());
}
}
Qui usiamo recv()
metodo che sospende il filo fino a quando qualcosa arriva sul canale, così al fine di riprendere il filo si solo bisogno di inviare qualcosa (valore unitario ()
in questo caso) attraverso il canale. Se la parte trasmittente del canale viene interrotta, recv()
restituirà Err(())
- lo usiamo per uscire dal ciclo.
I canali sono il modo più semplice e più naturale (IMO) per eseguire queste attività, ma non la più efficiente. Esistono altre primitive di concorrenza che puoi trovare nel modulo std::sync
. Appartengono a un livello inferiore rispetto ai canali, ma possono essere più efficienti in determinati compiti.
fonte
2014-10-05 07:30:24