You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tauri Builder外的新线程中触发Rust后端事件?

Tauri独立线程触发前端事件解决方法

方法一:在setup中创建线程并传递克隆的AppHandle

将线程创建逻辑移至setup方法内,通过克隆AppHandle让线程拥有发送事件的能力——AppHandle实现了Send + Sync + 'static,可安全跨线程使用。

fn main() {
    tauri::Builder::default()
        .setup(|app| {
            // 克隆AppHandle,供子线程使用
            let app_handle = app.handle().clone();
            
            std::thread::spawn(move || {
                // 执行mDNS服务浏览逻辑
                // 发现服务时发送事件到前端
                let service_data = "这里替换为实际的Bonjour服务信息";
                if let Err(e) = app_handle.emit_all("service-discovered", service_data) {
                    eprintln!("发送事件失败: {}", e);
                }
            });
            
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("Tauri应用启动失败");
}

方法二:全局静态变量存储AppHandle(适用于提前创建线程的场景)

如果必须在Tauri Builder启动前创建线程,可使用OnceCell存储全局AppHandle,线程等待该变量初始化完成后再发送事件。

use std::sync::OnceCell;
use tauri::AppHandle;

// 全局静态变量,用于存储初始化后的AppHandle
static APP_HANDLE: OnceCell<AppHandle> = OnceCell::new();

fn main() {
    // 提前创建mDNS浏览线程
    std::thread::spawn(move || {
        // 等待AppHandle完成初始化
        let app_handle = APP_HANDLE.get().expect("AppHandle未完成初始化");
        
        // 持续浏览服务并发送事件
        loop {
            // 模拟发现服务的逻辑
            let new_service = "新发现的Bonjour服务";
            if let Err(e) = app_handle.emit_all("service-discovered", new_service) {
                eprintln!("发送事件失败: {}", e);
            }
            std::thread::sleep(std::time::Duration::from_secs(2));
        }
    });

    // 启动Tauri应用
    tauri::Builder::default()
        .setup(|app| {
            // 将AppHandle存入全局变量
            APP_HANDLE.set(app.handle().clone()).expect("AppHandle已被设置");
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("Tauri应用启动失败");
}

前端监听事件示例

在前端代码中通过Tauri的事件API监听服务发现事件:

import { listen } from '@tauri-apps/api/event';

// 监听服务发现事件
listen('service-discovered', (event) => {
    console.log('发现Bonjour服务:', event.payload);
    // 这里添加服务数据的处理逻辑
});

关键注意事项

  • AppHandle是线程安全的,克隆后可在任意线程中调用emit_all向所有前端窗口发送事件。
  • 使用全局变量方案时,务必确保线程在APP_HANDLE赋值完成后再执行发送逻辑,避免触发panic。
  • mDNS浏览线程需处理好生命周期,可通过原子布尔变量等方式,在应用退出时优雅终止线程。

内容的提问来源于stack exchange,提问作者Michael Perelman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:12:55