2014-10-05 9 views
7

Ich habe einen Thread mit einer Endlosschleife und Timer im Inneren erzeugt.Wie man einen Rust-Thread von einem anderen Thread beendet oder aussetzt?

thread::spawn(|| { 
    let mut timer = Timer::new().unwrap(); 
    let periodic = timer.periodic(Duration::milliseconds(200)); 
    loop { 
     periodic.recv(); 

     // Do my work here 
    } 
}); 

Beachten Sie, dass während dieses Beispiel vor Rust erstellt wurde 1.0 und die spezifischen Typen geändert oder seitdem entfernt worden ist, die allgemeine Frage und Konzept gültig

Nach einer gewissen Zeit bleiben, basierend auf bestimmten Bedingungen, Ich muss diesen Thread von einem anderen Teil meines Programms beenden. Mit anderen Worten, ich möchte nur die Endlosschleife verlassen. Wie kann ich das richtig machen? Außerdem, wie könnte ich diesen Thread anhalten und später fortsetzen?

Ich habe versucht, eine globale unsichere Flagge zu verwenden, um die Schleife zu unterbrechen, aber ich denke, dass diese Lösung nicht gut aussieht.

Antwort

12

Edit: für Rust 1.x aktualisiert

Für beide Aufgaben (beenden und einen Thread Suspend) Sie können Kanäle verwenden.

Hier ist, wie ein Faden von außen beendet werden konnte:

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(()); 
} 

Das heißt, bei jeder Iteration eines Arbeitnehmers Schleife überprüfen wir, ob uns jemand durch einen Kanal informiert. Wenn ja oder wenn das andere Ende des Kanals den Rahmen verlassen hat, brechen wir einfach die Schleife.

Hier ist, wie ein Thread könnte „suspendiert“ und „Wiederaufnahme“:

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(()); 
    } 
} 

Hier verwenden wir recv() Methode, die den Faden aussetzt, bis etwas auf dem Kanal ankommt, so um den Faden wieder aufnehmen Sie muss nur etwas (Einheitswert () in diesem Fall) durch den Kanal senden. Wenn das sendende Ende des Kanals gelöscht wird, gibt recv()Err(()) zurück - wir benutzen dies, um die Schleife zu verlassen.

Kanäle sind die einfachste und natürlichste (IMO) Art, diese Aufgaben zu erledigen, aber nicht die effizienteste. Es gibt andere Concurrency-Primitive, die Sie im std::sync Modul finden können. Sie gehören zu einer niedrigeren Ebene als Kanäle, können aber in bestimmten Aufgaben effizienter sein.

Verwandte Themen