Repository: tauri
Issue: [bug] CloseRequested:: prevent_close() is invalid
Labels: type: bug,status: needs triage

### Describe the bug

I use tauri to listen for window close events. I capture the close request in main_window.on_window_event and use api.prevent_close(); Prevents the default shutdown behavior, but he closes the program anyway。

permissions
```
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": [
    "main"
  ],
  "permissions": [
    "core:default",
    "shell:allow-open",
    "fs:default",
    "clipboard-manager:default",
    "dialog:default",
    {
      "identifier": "http:default",
      "allow": [{ "url": "https://*.tauri.app" }],
      "deny": [{ "url": "https://private.tauri.app" }]
    },
    {
      "identifier": "fs:allow-exists",
      "allow": [
        {
          "path": "$APPDATA/*"
        }
      ]
    }
  ]
}
```

run
```
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    // 初始化日志
    sys_log::init_logger();
    log::info!("init system start");

    let current_dir = std::env::current_dir().expect("路径错误");
    let data_path = current_dir.join(DATA_PATH);
    if !data_path.exists() {
        let _ = std::fs::create_dir_all(&data_path).expect("创建数据文件夹失败");
    }
    // let data_path = data_path.as_path();

    #[allow(unused_mut)]
    let mut builder = tauri::Builder::default();

    #[allow(unused_mut)]
    let mut app = builder
        .plugin(tauri_plugin_dialog::init())
        .plugin(tauri_plugin_clipboard_manager::init())
        .plugin(tauri_plugin_shell::init())
        .invoke_handler(tauri::generate_handler![greet])
        .setup(move |app| {
            register_database(app, data_path.clone())?;
            // The shutdown request event is registered here
            close_dialog::dialog(app.handle());
            Ok(())
        })
        .build(tauri::generate_context!())
        .expect("error while building tauri application");

    log::info!("init system ready");
    app.run(|_app_handle, e| {
        match e {
            tauri::RunEvent::Ready => {
                log::info!("Application is ready.");
            },
            _ => {}
        }
    });
}
```


dialog
```
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use tauri::{AppHandle, Manager, WindowEvent};
use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogKind};

pub fn dialog(app: &AppHandle) {
    let main_window = Arc::new(app.get_webview_window("main").unwrap());
    let dialog_shown = Arc::new(AtomicBool::new(false));
    let dialog_shown_clone = dialog_shown.clone();

    let app = Arc::new(app.clone());
    let main_window_clone = main_window.clone();

    main_window.on_window_event(move |event| {
        if let WindowEvent::CloseRequested { api, .. } = event {
            if !dialog_shown_clone.load(Ordering::Relaxed) {
                log::info!("Confirm to exit the current program?");

                // 标记对话框已显示
                dialog_shown_clone.store(true, Ordering::Relaxed);
                // 阻止默认的关闭行为
                api.prevent_close();

                let app = app.clone();
                let main_window_clone = main_window_clone.clone();
                let dialog_shown_clone = dialog_shown.clone();

                // 使用 tokio 或 async-std 来处理异步任务
                tauri::async_runtime::block_on( async move {
                    handle_exit_dialog(app, main_window_clone, dialog_shown_clone).await
                });
            }
        }
    });
}

async fn handle_exit_dialog(
    app: Arc<AppHandle>,
    main_window: Arc<tauri::WebviewWindow>,
    dialog_shown: Arc<AtomicBool>,
) {
    log::info!("Wait for the user to choose whether to quit the program!");
    app.dialog()
        .message("确定退出吗?？")
        .kind(MessageDialogKind::Info)
        .title("Information")
        .buttons(MessageDialogButtons::OkCancelCustom(
            format!("退出"),
            format!("取消"),
        ))
        .show(move |result| match result {
            true => {
                log::info!("Exit application");
                main_window
                    .close()
                    .unwrap_or_else(|e| log::error!("Failed to close window: {}", e));
            },
            false => {
                log::info!("Cancels exiting the current program");
                dialog_shown.store(false, Ordering::Relaxed);
            }
        });
}
```



### Reproduction

_No response_

### Expected behavior

I want a dialog box to pop up when I close the program and let the user confirm

### Full `tauri info` output

```text
[✔] Environment
    - OS: Mac OS 14.5.0 x86_64 (X64)
    ✔ Xcode Command Line Tools: installed
    ✔ rustc: 1.84.0 (9fc6b4312 2025-01-07)
    ✔ cargo: 1.84.0 (66221abde 2024-11-19)
    ✔ rustup: 1.27.1 (54dd3d00f 2024-04-24)
    ✔ Rust toolchain: stable-x86_64-apple-darwin (default)
    - node: 22.11.0
    - yarn: 1.22.22
    - npm: 10.9.0


[-] Packages
    - tauri 🦀: 2.2.0
    - tauri-build 🦀: 2.0.4
    - wry 🦀: 0.48.0
    - tao 🦀: 0.31.1
    - @tauri-apps/api : 2.2.0
    - @tauri-apps/cli : 2.2.2

[-] Plugins
    - tauri-plugin-shell 🦀: 2.2.0
    - @tauri-apps/plugin-shell : 2.2.0
    - tauri-plugin-fs 🦀: 2.2.0
    - @tauri-apps/plugin-fs : not installed!
    - tauri-plugin-dialog 🦀: 2.2.0
    - @tauri-apps/plugin-dialog : 2.2.0
    - tauri-plugin-http 🦀: 2.2.0
    - @tauri-apps/plugin-http : not installed!

[-] App
    - build-type: bundle
    - CSP: unset
    - frontendDist: ../dist
    - devUrl: http://localhost:1420/
    - framework: Vue.js
    - bundler: Vite
```


### Stack trace

```text
Can print out this log: 'Wait for the user to choose whether to quit the program! '
```


### Additional context

```
[build-dependencies]
tauri-build = { version = "2", features = [] }

[dependencies]
tauri = { version = "2", features = [] }
tauri-plugin-shell = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
chrono = "0.4"
quick-xml = "0.37.2"
tempfile = "3.15.0"
thiserror = "2.0"
zip = "2"
walkdir = "2.5.0"
# tokio = {version = "1.43.0", features = ["full"] }
tauri-plugin-fs = "2"
tauri-plugin-clipboard-manager = "2.2.0"
tauri-plugin-dialog = "2"
tauri-plugin-http = "2"
sqlx = { version = "0.8", default-features = false, features = ["runtime-tokio-native-tls", "sqlite", "macros"] }
# rusqlite = {version = "0.32.1", features = ["bundled-sqlcipher"] }
urlencoding = "2.1"
log = "0.4"
log4rs = {version = "1.3", features = ["gzip"] }

[dev-dependencies]
tokio = {version = "1.43.0", features = ["full"] }
```