rustshutdowntauri

Close Tauri window without closing the entire app


I use Tauri in my Rust project, but it is not the main component and runs on another thread (on platforms where that is available). Closing the window currently stops the entire app (most of which is command-line based) and I haven't found a way to change this behavior.

I currently have this minimal example:

fn main() {
    tauri::Builder::default()
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    println!("Hello after tauri");
}

The print after the application never triggers. If you try to move it to a separate thread, the entire application still closes:

fn main() {
    std::thread::spawn(|| {
        tauri::Builder::default()
            .any_thread()
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    });
    loop {
        println!("Hello during tauri!");
        std::thread::sleep(std::time::Duration::from_secs(1));
    }
}

Solution

  • The loop wouldn't work, because tauri has its own runtime, so your loop code wouldn't be executed until Tauri's runtime stops.

    Tauri architecture

    So depending on what you're trying to do there are several things you can do.

    1. Not closing Tauri window:

    Prevent app from exiting:

    tauri::Builder::default()
      .build(tauri::generate_context!())
      .expect("error while building tauri application")
      .run(|_app_handle, event| match event {
        tauri::RunEvent::ExitRequested { api, .. } => {
          api.prevent_exit();
        }
        _ => {}
      });
    

    Or just close the window without closing the app (this is how it's done on Mac):

    tauri::Builder::default().on_window_event(|event| match event.event() {
      tauri::WindowEvent::CloseRequested { api, .. } => {
        event.window().hide().unwrap();
        api.prevent_close();
      }
      _ => {}
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
    

    2. Running your loop in parallel in a separate thread:

    tauri::Builder::default()
                .setup(|app| {
                   let handle = app.handle();
                   tauri::async_runtime::spawn(async move {
                       loop {
                          println!("Hello during tauri!");
                          // access tauri's app handle here
                          std::thread::sleep(std::time::Duration::from_secs(1));
                       }
                   });
                })
                .run(tauri::generate_context!())
                .expect("error while running tauri application");
    

    3. Have your logic done in async way:

    If you can keep it simple, running a loop inside a command would be quick and easy.

    I would recommend to research on how async and Runtimes work in Rust, here's most popular Tokio's Runtime, since it's mostly what you'll end up with in production.