#Egui
14 messages · Page 1 of 1 (latest)
ok, probably the easier (and best) way is to use some multithreading
probably using a channel, but Arc<Mutex<Option<T>>> kind of stuff works as well
so, you can have the main thread just continue working, and when you press the button, it starts up a second thread that does work in the background.
your app state should have a field like task_reciever: Option<Reciever<ResultType>> that you can check on each time the gui is drawn, to monitor if the task is finished, and the thread that does the work has the corresponding sender
https://doc.rust-lang.org/stable/book/ch16-02-message-passing.html
https://doc.rust-lang.org/std/sync/mpsc/struct.Receiver.html#method.try_recv
The receiving half of Rust’s [channel] (or [sync_channel]) type. This half can only be owned by one thread.
would need a little more information than that, like the full error from running cargo check and maybe some of the code
you wont be able to make the second thread access any of the regular references. you need to have it be completely independent, and send the result in a channel
lets say, what would happen if the thread modified self at the same time as the main update loop? data races, garbage output. Obscure bug that breaks your program. What would happen if the thread tries to access self after the whole main event loop has already ended and self no longer exists? either more garbage output or the program would crash in a very uncontrolled way
these are the kinds of things its trying to protect you from
so instead of this part (im gonna ignore the weird naming) rs self.Player_Name = read::Read("C:\\Name.mmap".to_string()); self.Player_Race = read::Read("C:\\Race.mmap".to_string()); self.Player_Empire = read::Read("C:\\Empire.mmap".to_string());you should make some sort of struct rs struct Player { name: String, race: String, empire: String, }and then use a channel to send this struct from the worker thread to the main event loop.
by doing this immediately after spawning the thread handle1.join().unwrap();, youre running into the original problem again. If the operation that the thread is doing takes a full second to execute, the GUI is still going to be stuck on the same frame for the whole time. the work has to be done independently so it doesnt stop the GUI from redrawing itself freely
so your program state would have the field like task_reciever: Option<Reciever<Player>>, which would be None by default.
When you click the button that starts the heavy work, you would do like this (in this example its giving a path to read a file from, and the worker thread reads the file and constructs the player struct from it) ```rs
let path = path.clone();
let (tx, rx): (Sender<Player>, Receiver<Player>) = mpsc::channel();
std::thread::spawn(move || {
let file_contents = std::fs::read_to_string(path);
// parse a Player out of the file contents
let player = ...;
tx.send(player).expect("Failed to send player");
});
self.task_reciever = Some(rx);now youve started the task to be ran in the background, without blocking the UI. and the fact that `self.task_receiver` is now `Some` with a receiver instead of `None` indicates that the work is currently being done in the background. You can use this to run some code like this in another part of the regular update loop, every time instead of just on a button press. rs
if let Some(rx) = &self.task_reciever { // checks whether the computation is in progress, and puts the receiver into rx if yes.
if let Ok(player) = rx.try_recv() { // if this returns Ok, that means the computation is finished. else, the gui can continue running as normal and check for progress again on the next time that the update function gets run.
// Here you can do whatever you wanted to do with the result
self.Player_Name = player.name;
self.Player_Race = player.race;
self.Player_Empire = player.empire;
self.task_reciever = None; // the computation is done, and the reciever can now be set to None to indicate that
}
}```
so do you understand why the UI is freezing? the update function is necessary for drawing the UI to the screen. So if update takes long, there's nothing else drawing the UI for you, you blocked the thing that's supposed to be doing that.
I have no idea about stuff like that. But maybe you can ask in #dark-arts or something, or make a new post here with a more appropriate name