2014-10-05 81 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模块中找到。它们属于比渠道低的层次,但在特定任务中可以更有效率。