Update signal from another thread #1797
-
Maybe is not possible because this library is primary focus on web application but using Here's an example using the use gtk::{prelude::*, Application, ApplicationWindow, Button};
use leptos::*;
const APP_ID: &str = "dev.leptos.Counter";
// Basic GTK app setup from https://gtk-rs.org/gtk4-rs/stable/latest/book/hello_world.html
fn main() {
let _ = create_runtime();
// Create a new application
let app = Application::builder().application_id(APP_ID).build();
// Connect to "activate" signal of `app`
app.connect_activate(build_ui);
// Run the application
app.run();
}
fn build_ui(app: &Application) {
let button = counter_button();
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("Leptos-GTK")
.child(&button)
.build();
// Present window
window.present();
}
fn counter_button() -> Button {
let (value, set_value) = create_signal(0);
// Create a button with label and margins
let button = Button::builder()
.label("Count: ")
.margin_top(12)
.margin_bottom(12)
.margin_start(12)
.margin_end(12)
.build();
// here I need to update the value from another thread
tokio::spawn(async move {
loop {
sleep(Duration::from_millis(10000));
println!("update");
set_counter.update(|counter| *counter += 1);
}
});
create_effect({
let button = button.clone();
move |_| {
button.set_label(&format!("Count: {}", value()));
}
});
button
} With this code, I get There's a way to make this example work? For reference in my real project, I need to listen to a hyprland event using the tokio::spawn({
async move {
let mut event_listener = EventListener::new();
event_listener.add_active_window_change_handler(move |e| {
set_counter.update(|counter| *counter += 1);
});
event_listener
.start_listener_async()
.await
.expect("failed to start active window listener");
}
}); |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
No, the reactive system itself is explicitly single-threaded. I'm surprised that it even compiled, but I guess it's because you are sending a You can't update a signal from another thread. You could send a channel transmitter across threads and listen for it on this thread, and then update the signal. I don't know much more about this and have never tried it, unfortunately. |
Beta Was this translation helpful? Give feedback.
-
Ok, thanks. The final code looks like this and it seems working. const APP_ID: &str = "dev.leptos.Counter";
// Basic GTK app setup from https://gtk-rs.org/gtk4-rs/stable/latest/book/hello_world.html
fn main() {
let _ = create_runtime();
// Create a new application
let app = Application::builder().application_id(APP_ID).build();
// Connect to "activate" signal of `app`
app.connect_activate(build_ui);
// Run the application
app.run();
}
fn build_ui(app: &Application) {
let button = counter_button();
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("Leptos-GTK")
.child(&button)
.build();
// Present window
window.present();
}
fn counter_button() -> Button {
let (value, set_value) = create_signal(0);
// Create a button with label and margins
let button = Button::builder()
.label("Count: ")
.margin_top(12)
.margin_bottom(12)
.margin_start(12)
.margin_end(12)
.build();
//Here I need to update the value from another thread
//The `spawn` function is the same present on this repo https://github.com/rodrigorc/gidle_future
// I changed some minor stuff only
spawn(async move {
loop {
time::sleep(Duration::from_millis(1000)).await;
set_counter.update(|counter| *counter += 1);
}
});
create_effect({
let button = button.clone();
move |_| {
button.set_label(&format!("Count: {}", value()));
}
});
button
} |
Beta Was this translation helpful? Give feedback.
-
Hi, very interesting! For this reason, currently, I'm using another library futures-signals. If could be useful here there's the code before the switch to |
Beta Was this translation helpful? Give feedback.
No, the reactive system itself is explicitly single-threaded. I'm surprised that it even compiled, but I guess it's because you are sending a
WriteSignal
which is really just an index type and so doesn't get inferred as!Send
.You can't update a signal from another thread. You could send a channel transmitter across threads and listen for it on this thread, and then update the signal. I don't know much more about this and have never tried it, unfortunately.