2014-10-05 19 views
7

Sonsuz döngü ve zamanlayıcının bulunduğu bir iş parçacığı oluşturdum.Pas ipliğini başka bir dişten nasıl sonlandırır veya askıya alırsınız?

bu örnek Rust 1.0 önce oluşturulmuş ve belirli türleri değişmiş veya o zamandan beri kaldırılmış iken, genel soru kavram olmaya devam ettiğini Not
thread::spawn(|| { 
    let mut timer = Timer::new().unwrap(); 
    let periodic = timer.periodic(Duration::milliseconds(200)); 
    loop { 
     periodic.recv(); 

     // Do my work here 
    } 
}); 

bazı koşullara dayanan bir süre sonra

geçerli, Bu konuyu programımın başka bir bölümünden sonlandırmalıyım. Başka bir deyişle, sadece sonsuz döngüden çıkmak istiyorum. Bunu nasıl doğru yapabilirim? Ayrıca, bu iş parçacığını nasıl askıya alabilirim ve daha sonra nasıl devam edebilirim?

Döngüyü kırmak için global güvensiz bayrağı kullanmaya çalıştım ama bence bu çözüm hoş görünmüyor.

cevap

12

Düzenleme: Hem bu görevleri için Pas 1.x

için güncellenmiş (sonlandırmak ve bir iş parçacığı askıya) Eğer kanalları kullanabilirsiniz. Birisi bir kanaldan bize bildirilmesi durumunda

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

, bir işçi döngünün her tekrarında denetlenmektedir: Burada

bir iplik dışarıdan sonlandırılabilir nasıl olduğunu. Eğer evetse veya kanalın diğer ucu kapsam dışıysa, sadece döngüyü kırarız. İşte

bir iş parçacığı "askıya" ve "yeniden" şekli ele alınmıştır:

Burada bir şey kanalda gelene kadar iplik devam etmesi için, böylece evreyi askıya recv() yöntemi kullanmak
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(()); 
    } 
} 

sen Kanal üzerinden sadece bir şey göndermelisiniz (bu durumda () birim değeri). Kanalın iletim ucu düşerse, recv()Err(())'u döndürür - bu döngüden çıkmak için kullanırız.

Kanallar, bu görevleri gerçekleştirmenin en kolay ve en doğal (IMO) yoludur, ancak en verimli olanı değildir. std::sync modülünde bulabileceğiniz diğer eşzamanlılık ilkeleri vardır. Kanallardan daha düşük bir seviyeye aittirler, ancak belirli görevlerde daha verimli olabilirler.

İlgili konular