2014-10-05 79 views
7

我產生了一個線程,裏面有一個無限循環和計時器。如何終止或掛起另一個線程的生鏽線程?

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

     // Do my work here 
    } 
}); 

請注意,雖然這個例子是鐵鏽1.0之前創建的特定類型已經改變或自那以後被刪除,一般的問題和概念仍然有效

根據一些條件來過了一段時間,我需要從我的程序的另一部分終止此線程。換句話說,我只想退出無限循環。我怎樣才能正確地做到這一點?另外,我如何暫停此線程並稍後恢復?

我試圖使用全局不安全標誌來打破循環,但我認爲這個解決方案看起來不太好。

回答

12

編輯:更新的鏽1.x的

對於這兩個任務(終止和暫停線程),你可以使用信道。

下面是一個線程可以在外部終止:

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

也就是說,一名工人循環的每個迭代,我們檢查,如果有人通知我們通過一個通道。如果是,或者如果頻道的另一端已經超出範圍,我們只是打破循環。

下面是一個線程可以「暫停」和「恢復」:

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

這裏我們使用recv()方法,掛起線程,直到東西到達通道上,所以爲了恢復該線程你只需要通過該通道發送一些東西(在這種情況下爲單元值())。如果通道的發送端被丟棄,recv()將返回Err(()) - 我們用它來退出循環。

渠道是最容易和最自然(IMO)的方式來做這些任務,但不是最有效的。還有其他併發原語可以在std::sync模塊中找到。它們屬於比渠道低的層次,但在特定任務中可以更有效率。