如何在生成的 tauri 异步运行时线程中使用托管 Tauri 状态变量?

问题描述 投票:0回答:1

我是 rust 新手,所以这是一个关于 tauri + rust 的问题。 我正在尝试构建这个应用程序,其中有一个命令启动一个线程,该线程向rabbitmq发布许多消息,然后在发布完成后发出一个事件。 我有一个使用

ConnectionMutex
的状态 API 的托管
tauri
结构,并且我还获取了窗口句柄来发出事件。 代码如下所示:

use tauri::async_runtime::Mutex;
pub struct ConnectionMutex(pub Mutex<Option<RabbitMqConnection>>);


#[tauri::command]
pub async fn publish_message(
    connection_mutex: tauri::State<'_, ConnectionMutex>,
    window: tauri::Window,
) -> Result<(), String> { 
    tauri::async_runtime::spawn(async move {
        let lock = connection_mutex
            .0
            .try_lock()
            .map_err(|_| String::from("cannot change connection while it is being used"))
            .unwrap();
        let conn = lock.as_ref().ok_or("no rabbitmq connection").unwrap();

        let _ = rabbitmq::publishing::publish(
            &conn.target,
            &conn.channel,
            window,
        )
        .await;
    });

    Ok(())
}

我收到编译器错误:

borrowed data escapes outside of function
。这个错误对我来说是有意义的,我明白为什么这不安全,因为 rust 借用检查器无法再跟踪借用的变量,并且无法在正确的时间释放它。 然而,我不知道在 Rust 中实现这种东西的正确方法。

我还尝试将

State
变量的生命周期设置为静态,如下所示:

#[tauri::command]
pub async fn publish_message(
    connection_mutex: tauri::State<'static, ConnectionMutex>,
    window: tauri::Window,
) -> Result<(), String>

但我得到了一个不同的错误:

__tauri_message__ does not live long enough

感谢您的帮助!

multithreading asynchronous rust mutex tauri
1个回答
0
投票

一种常见的方法是将

Mutex
包装在
Arc
中,以便您可以跨
Mutex
任务安全地共享对底层
async
的引用。 (另请参阅文档中的示例)。

所以你的

ConnectionMutex
可能看起来像:

#[derive(Clone)]
pub struct ConnectionMutex(pub Arc<Mutex<Option<RabbitMqConnection>>>);

然后,当您想要在生成

async
任务时传递连接时,您首先
clone()
ConnectionMutex
为任务提供它自己的引用副本。

#[tauri::command]
pub async fn publish_message(
    connection_mutex: tauri::State<'_, ConnectionMutex>,
    window: tauri::Window,
) -> Result<(), String> {
    let connection = connection_mutex.clone();

    tauri::async_runtime::spawn(async move {
        let lock = connection
            .0
            .try_lock()
            .map_err(|_| String::from("cannot change connection while it is being used"))
            .unwrap();
        let conn = lock.as_ref().ok_or("no rabbitmq connection").unwrap();

        let _ = rabbitmq::publishing::publish(
            &conn.target,
            &conn.channel,
            window,
        )
        .await;
    });

    Ok(())
}
© www.soinside.com 2019 - 2024. All rights reserved.