Is there some way for backend to emit event actively? #5111
-
I'm tring to use hotwatch to monitor folders for backups. If any changes happen, expect to emit an event to frontend to update pages. Then i found that it's not able to access AppHandle or Window in regular struct. I have tried using lifetime, but as Tauri: accessing-an-apphandle-in-commands mention, it seems there's no way to mantain a long enough life time. pub struct MonitorHandler<'a> {
pub watcher: Hotwatch;
pub app_handler: Option<&'a AppHandle>
}
impl MonitorHandler<'_> {
pub fn initialize_app_handler(&mut self, handler: AppHandle) {
self.app_handler = Some(&handler);
}
pub fn append_target(path: &str) {
self.watcher.watch(path, |event| {
self.app_handler.emit_all("update");
})
}
}
// whitch shows error
89 | pub fn initialize_app_handler(&mut self, handler: AppHandle) {
| --------- has type `&mut MonitorHandler<'1>`
90 | self.app_handler = Some(&handler);
| ------------------------^^^^^^^^-
| | |
| | borrowed value does not live long enough
| assignment requires that `handler` is borrowed for `'1`
...
93 | }
| - `handler` dropped here while still borrowed I have tried add app handle when setup, but it still not work, and with the same life time problem. // main.rs
...
fn main() {
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor }));
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(store)
.setup(|app| {
store.0.lock().unwrap().initialize_app_handler(app.app_handle());
})
.invoke_handler(tauri::generate_handler![
initialize_app_handler
])
.run(context)
.expect("error while running tauri application");
}
// which will occurs
|
40 | let store = MonitorHandler(Mutex::new(MonitorHandler {
| ----- move occurs because `store` has type `MonitorHandler<'_>`, which does not implement the `Copy` trait
...
51 | .manage(store)
| ----- value moved here
52 | .setup(|app| {
| ^^^^^^^^^^ value used here after move
53 | store.0.lock().unwrap().initialize_app_handler(app.app_handle());
| ------- use occurs due to use in closure I'm not familiar with rust and tauri, so is there some way to access the AppHandle or Window in my situation? or i have to do this in another way? Here's my origin code // handler.rs
// in this case, whether it's AppHandle or Window, the program will just stuck and not able to anything
pub struct MonitorHandler {
pub watcher: Hotwatch;
pub app_handler: Option<AppHandle>
}
impl MonitorHandler {
pub fn initialize_app_handler(&mut self, handler: AppHandle) {
self.app_handler = Some(handler.clone());
}
}
pub struct MonitorHandler(pub Mutex<MonitorHandler>);
// main.rs
use hotwatch::Hotwatch;
use tauri::{ Manager, AppHandle };
use crate::handler::MonitorHandler;
#[tauri::command]
pub fn initialize_app_handler(monitor: State<MonitorHandler>, app_handler: AppHandle) -> bool {
monitor.0.lock().unwrap().initialize_app_handler(app_handler);
true
}
fn main() {
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
let store = MonitorHandler(Mutex::new(MonitorHandler{ watcher: monitor }));
let context = tauri::generate_context!();
tauri::Builder::default()
.manage(store)
.setup()
.invoke_handler(tauri::generate_handler![
initialize_app_handler
])
.run(context)
.expect("error while running tauri application");
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
The code at the bottom, the "origin code", looks correct to me in terms of AppHandle usage, and it can't really get stuck because of the AppHandle itself either. It's probably some kind of deadlock happening with the mutex or watcher 🤔 I did copy that bottom code snippet into my app and it didn't block anything. And also here's how you could make it a little easier: // handler.rs
// in this case, whether it's AppHandle or Window, the program will just stuck and not able to anything
pub struct MonitorHandler {
pub watcher: Hotwatch,
pub app_handler: Option<AppHandle>
}
impl MonitorHandler {
pub fn initialize_app_handler(&mut self, handler: AppHandle) {
self.app_handler = Some(handler.clone());
}
} // main.rs
use hotwatch::Hotwatch;
use tauri::{ Manager, AppHandle };
use crate::handler::MonitorHandler;
pub struct MonitorHandlerWrapper(pub Mutex<MonitorHandler>);
fn main() {
tauri::Builder::default()
.setup(|app| {
let handle = app.handle();
let monitor = Hotwatch::new().expect("failed to initialize monitor_handler");
app.manage(MonitorHandlerWrapper(Mutex::new(MonitorHandler { app_handler: handle, watcher: monitor })));
Ok(())
})
.invoke_handler(tauri::generate_handler![])
.run(tauri::generate_context!())
.expect("error while running tauri application");
} This one doesn't make the app getting stuck for me either btw. |
Beta Was this translation helpful? Give feedback.
The code at the bottom, the "origin code", looks correct to me in terms of AppHandle usage, and it can't really get stuck because of the AppHandle itself either. It's probably some kind of deadlock happening with the mutex or watcher 🤔
I did copy that bottom code snippet into my app and it didn't block anything.
And also here's how you could make it a little easier: