Editor's note-此示例创建于Rust 1.0之前,自那时起,特定类型已更改或删除.一般问题和概念仍然有效.

我产生了一个线程,里面有无限循环和计时器.

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

        // Do my work here
    }
});

基于某些条件,经过一段时间后,我需要从程序的另一部分终止该线程.换句话说,我想退出无限循环.我怎样才能正确地做到这一点?另外,我怎样才能暂停这个线程并在以后继续呢?

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

推荐答案

对于终止和挂起线程,可以使用通道.

Terminated externally

在worker循环的每次迭代中,我们判断是否有人通过渠道通知我们.如果是,或者通道的另一端超出了范围,我们就打破循环.

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

Suspending and resuming

我们使用recv(),它会暂停线程,直到有东西到达通道.为了恢复线程,需要通过通道发送一些内容;在这种情况下,单位值为().如果信道的传输端被丢弃,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(());
    }
}

Other tools

渠道是完成这些任务最简单、最自然(IMO)的方式,但不是最有效的方式.在std::sync模块中还可以找到其他并发原语.它们可能比某个特定级别的任务更高效.

Rust相关问答推荐

trait 中self 的显式生命周期似乎导致E0499无法在循环中多次borrow * emits 器作为可变的

这种获取-释放关系是如何运作的?

带参考文献的 rust 元组解构

如何将映射反序列化为具有与键匹配的字段的定制 struct 的向量?

作为1字节位掩码的布尔值 struct

如何创建一个可变的嵌套迭代器?

对reqwest提供的这种嵌套JSON struct 进行反序列化

Rust Option 的空显式泛型参数

面临意外的未对齐指针取消引用:地址必须是 0x8 的倍数,但为 0x__错误

我可以禁用发布模式的开发依赖功能吗?

go 重并堆积MPSC通道消息

为什么带有生命周期指定的方法不能被调用两次?

如何使用 Rust Governor 为每 10 秒 10 个请求创建一个 RateLimiter?

如何判断服务器是否正确接收数据

n 个范围的笛卡尔积

为什么在 rust 中删除 vec 之前应该删除元素

为什么拥有 i32 所有权的函数需要它是可变的?

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

Cargo:如何将整个目录或文件包含在功能标志中?

`if let` 只是另一种编写其他 `if` 语句的方式吗?