我生成了一个带有无限循环和计时器的线程。

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

        // Do my work here
    }
});

在基于某些条件的一段时间后,我需要从程序的另一部分终止此线程。换句话说,我想退出无限循环。如何正确执行此操作?此外,我如何暂停该线程并在以后恢复它?

我试图使用全局不安全标志来打破循环,但是我认为这种解决方案看起来不太好。

最佳答案

对于终止和挂起线程,您可以使用 channel 。

外部终止

在worker循环的每次迭代中,我们都会检查是否有人通过 channel 通知了我们。如果是,或者 channel 的另一端超出范围,我们将中断循环。

use std::io::{self, BufRead};
use std::sync::mpsc::{self, TryRecvError};
use std::thread;
use std::time::Duration;

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()挂起线程,直到有什么东西到达 channel 。为了恢复线程,您需要通过 channel 发送一些东西。在这种情况下,单位值为()。如果 channel 的发送端被丢弃,recv()将返回Err(())-我们使用它退出循环。
use std::io::{self, BufRead};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;

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

其他工具

channel 是完成这些任务的最简单,最自然(IMO)的方法,但不是最有效的方法。您还可以在 std::sync 模块中找到其他并发原语。它们属于比 channel 低的级别,但在特定任务中可以更有效。

关于multithreading - 如何终止或暂停来自另一个线程的Rust线程?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26199926/

10-11 22:59
查看更多