Run on main thread or equivalent?

Is there a way to execute code back on main thread from child thread ? Something like run on ui thread in Kotlin or Swift.
For example:

use hotwatch::{Hotwatch, Event, EventKind};

let mut structure=S::new();

let mut hotwatch = Hotwatch::new().expect("hotwatch failed to initialize!");
hotwatch.watch("war.png", move |event: Event| {
    if let EventKind::Modify(_) = event.kind {
        thread.main(move||{
             structure.do_something_on_main_thread("war.png");          
        };
    }
}).expect("failed to watch file!");

You can use message channels.

use std::sync::mpsc;
use std::thread;

fn main() {
    let (tx, rx) = mpsc::channel();

    thread::spawn(move || {
        let val = String::from("hi");
        tx.send(val).unwrap();
        println!("val is {}", val);
    });

    let received = rx.recv().unwrap();
    println!("Got: {}", received);
}

See the Rust Book for more details.

https://doc.rust-lang.org/book/ch16-02-message-passing.html

But the main thread is blocked because I need a for loop to listen to all changes.
I need to use it with wininit which will block the main thread too.
Any idea?

If you mean the winin crate, this API seems useful.

1 Like

This typically works because your UI framework is in control of the main thread and has started an event loop that receives and dispatches events. That means it's pretty easy to access some sort of "handle" to that event loop (typically via a static variable) and post your own closures to be executed.

In your case, winit has an EventLoop type (your main event loop) which lets you create an EventLoopProxy for sending it messages. All you need to do is hook into that.

fn main() { 
  let event_loop: EventLoop<String> = EventLoopBuilder::with_user_event().build();
  let window = WindowBuilder::new().build(&event_loop).unwrap();

  let proxy = event_loop.create_proxy();

  std::thread::spawn(move || {
    // send the main thread a message via the proxy
    let _ = proxy.send_event("Hello, World".to_string());
  });

  event_loop.run(move |event, _, control_flow| {
    match event {
      Event::User(message) => println!("Message from thread: {message}"),
      _ => {},
  });
}

I haven't checked to see whether it compiles, but hopefully you get the gist.

2 Likes

That wasn't the answer to my question, but you solved my problem.
Many thanks, Michael and steffahn

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.