2014-10-05 2 views
7

무한 루프와 타이머가있는 스레드를 생성했습니다.다른 스레드에서 녹 스레드를 종료하거나 일시 중단하는 방법은 무엇입니까?

예 녹이 1.0 전에 생성하고 특정 유형의 변경 또는 이후 제거하는 동안, 일반적인 질문에 개념이 여전히 유의
thread::spawn(|| { 
    let mut timer = Timer::new().unwrap(); 
    let periodic = timer.periodic(Duration::milliseconds(200)); 
    loop { 
     periodic.recv(); 

     // Do my work here 
    } 
}); 

특정 조건에 기초하여 시간 후

유효 내 프로그램의 다른 부분에서이 스레드를 종료해야합니다. 즉 무한 루프를 빠져 나가기만을 원할뿐입니다. 이 작업을 올바르게 수행하려면 어떻게해야합니까? 또한 어떻게이 스레드를 일시 중단하고 나중에 다시 시작할 수 있습니까?

전역 안전하지 않은 플래그를 사용하여 루프를 중단하려고 시도했지만이 솔루션이 좋지 않다고 생각합니다.

답변

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

는 노동자 루프의 각 반복에 우리는 확인 : 여기

스레드 외부 종료 될 수있는 방법입니다. 예 또는 채널의 다른 끝이 범위를 벗어난 경우 루프를 중단합니다. 여기

스레드가 "일시 중지"와 "다시 시작"할 수있는 방법입니다 :

여기에 우리가 뭔가 채널에 도착할 때까지 스레드를 다시 시작하기 위해, 그래서 스레드를 일시 중단 recv() 방법을 사용
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()Err(())을 반환 할 것입니다. 우리는 이것을 사용하여 루프를 종료합니다.

채널은 이러한 작업을 수행하는 가장 쉽고 자연스러운 (IMO) 방법이지만 가장 효율적인 방법은 아닙니다. std::sync 모듈에서 찾을 수있는 다른 동시성 프리미티브가 있습니다. 그것들은 채널보다 낮은 레벨에 속하지만 특정 작업에서보다 효율적일 수 있습니다.

관련 문제