如题,在尝试把 notify 的 debouncer—watcher 改成 async 模式, 主要是为了把 watcher 顺利放结构体里然后内部调用,实验发现不改 async 的话整个程序会死等事件
提了个问题 Is there some way to make notify debounce watcher async?,照着说法改着改着发现对于 tx channel
两次 move 以后已经没办法保证其生命周期了
这是不是说明我这样的改法不行,或者有没有别的方法可以来让 debouncer-watcher 变成 async 的模式?
具体代码及报错如下, 这里 main loop 是为了测试
use notify::{RecursiveMode, Watcher, ReadDirectoryChangesWatcher, Error};
use std::{path::Path, time::Duration};
use chrono::prelude::*;
use notify_debouncer_full::{new_debouncer, Debouncer, FileIdMap, DebounceEventResult, DebouncedEvent};
use tokio::sync::mpsc::Receiver;
pub struct NotifyHandler {
pub notify_watcher: Option<Debouncer<ReadDirectoryChangesWatcher, FileIdMap>>,
pub receiver: Option<Receiver<Result<Vec<DebouncedEvent>, Vec<Error>>>>
}
impl NotifyHandler {
pub async fn initialize_notify_scheduler(&mut self) {
let (tx, rx) = tokio::sync::mpsc::channel(1);
let debouncer = new_debouncer(Duration::from_secs(3), None, move |result: DebounceEventResult| {
tokio::spawn(async move {
if let Err(e) = tx.send(result).await {
println!("Error sending event result: {:?}", e);
}
});
});
match debouncer {
Ok(watcher)=> {
println!("Initialize notify watcher success");
self.notify_watcher = Some(watcher);
self.receiver = Some(rx);
},
Err(error) => {
println!("{:?}", error);
}
}
}
pub async fn watch(&mut self, path: &str) -> notify::Result<()> {
let watch_path = Path::new(path);
if watch_path.exists() {
let is_file = watch_path.is_file();
println!("Valid path {} is file {}", path, is_file);
} else {
println!("watch path {:?} not exists", watch_path);
}
if let Some(mut watcher) = self.notify_watcher.take() {
watcher
.watcher()
.watch(watch_path, RecursiveMode::Recursive)?;
watcher
.cache()
.add_root(watch_path, RecursiveMode::Recursive);
if let Some(mut rx) = self.receiver.take() {
tokio::spawn(async move {
while let Some(res) = rx.recv().await {
match res {
Ok(events) => {
println!("events: {:?}", events);
},
Err(errors) => {
println!("errors: {:?}", errors)
}
}
}
});
}
}
Ok(())
}
}
#[tokio::main]
async fn main() {
let mut notifier: NotifyHandler = NotifyHandler { notify_watcher: None, receiver: None };
notifier.initialize_notify_scheduler().await;
notifier.watch("D:\\TEMP\\TestNote.txt").await.unwrap();
loop {
tokio::time::sleep(Duration::from_secs(3)).await;
let time: DateTime<Local> = Local::now();
println!("{}: Hello, world!", time.format("%Y-%m-%d %H:%M:%S").to_string());
}
}
expected a closure that implements the `FnMut` trait, but this closure only implements `FnOnce`
required for `[closure@src\main.rs:16:69: 16:103]` to implement `DebounceEventHandler`rustcClick for full compiler diagnostic
main.rs(16, 69): the requirement to implement `FnMut` derives from here
main.rs(18, 33): closure is `FnOnce` because it moves the variable `tx` out of its environment
main.rs(16, 25): required by a bound introduced by this call
lib.rs(634, 25): required by a bound in `new_debouncer`
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.