我正在try 创建一个线程来监视铁 rust 中的文件更改.我正在使用notify crate 来获取文件更改事件.

下面的代码显示了监视线程中运行的内容:

use std::{path::PathBuf, thread};

use log::{error, info};
use notify::Watcher;

fn main() {
    env_logger::init();

    let (tx, rx) = std::sync::mpsc::channel();

    thread::spawn({
        let config_path = PathBuf::from("config.toml");

        move || {
            let mut watcher =
                notify::recommended_watcher(move |res: Result<notify::Event, notify::Error>| {
                    match res {
                        Ok(event) => match event.kind {
                            notify::event::EventKind::Modify(notify::event::ModifyKind::Data(
                                notify::event::DataChange::Any,
                            )) => {
                                info!("Reloading config file");
                                tx.send(true).ok();
                            }
                            _ => (),
                        },
                        Err(e) => {
                            error!("Notify Error: {}", e);
                        }
                    }
                })
                .unwrap();
            watcher.watch(&config_path, notify::RecursiveMode::NonRecursive)
        }
    });

    loop {
        match rx.recv() {
            Ok(_) => {
                // reload config
            }
            Err(e) => {
                error!("Error while watching config file: {}", e);
                break;
            }
        }
    }
}
# Cargo.toml

[dependencies]
env_logger = "0.10.0"
log = "0.4.19"
notify = "6.0.1"

问题是,当我try 从通道接收时,我得到了输出Error while watching config file: receiving on a closed channel.

我期望发送器tx在不关闭通道的情况下移动到封闭器中.但不知何故,它被关闭了.

我已经判断了known problems个通知箱,但我认为没有任何与我的问题有关的.

推荐答案

watch()表示非阻塞.来自文档(重点是我的):

Begin人看着一条新路.

因此,这是一场一劳永逸的游戏.你不需要为它产生一个新的线程.事实上,当您这样做时,线程在watch之后立即终止,监视器被丢弃,通道被关闭.

以下是你应该做的:

fn main() {
    let (tx, rx) = std::sync::mpsc::channel();

    let config_path = PathBuf::from("config.toml");

    let mut watcher =
        notify::recommended_watcher(move |res: Result<notify::Event, notify::Error>| match res {
            Ok(event) => match event.kind {
                notify::event::EventKind::Modify(notify::event::ModifyKind::Data(
                    notify::event::DataChange::Any,
                )) => {
                    info!("Reloading config file");
                    tx.send(true).ok();
                }
                _ => (),
            },
            Err(e) => {
                error!("Notify Error: {}", e);
            }
        })
        .unwrap();
    watcher.watch(&config_path, notify::RecursiveMode::NonRecursive);

    loop {
        match rx.recv() {
            Ok(_) => {
                // reload config
            }
            Err(e) => {
                error!("Error while watching config file: {}", e);
                break;
            }
        }
    }
}

Rust相关问答推荐

将已知大小的切片合并成一个数组,

为什么类型需要在这个代码中手动指定,在rust?

铁 rust 干线无法使用PowerShell获取环境变量

获取字符串切片(&;str)上的切片([ia..ib])返回字符串

无法理解铁 rust &S错误处理

如何指定不同的类型来常量Rust中的泛型参数?

如何正确重新排列代码以绕过铁 rust 借入判断器?

获取已知数量的输入

为什么我必须使用 PhantomData?在这种情况下它在做什么?

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

仅在使用 &mut 或线程时borrow 的数据在闭包之外转义?

方法可以被误认为是标准特性方法

返回优化后的标题:返回异步块的闭包的类型擦除

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

在 Rust 中,我如何处理请求 javascript 的页面?

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

在 Rust 中返回对枚举变体的引用是个好主意吗?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

守卫如何影响匹配语句?

类型参数不受 impl 特征、自身类型或谓词的约束