rust EGUI与后台线程交互

n53p2ov0  于 2023-01-30  发布在  其他
关注(0)|答案(1)|浏览(189)

我的目标是有一个每秒计数的后台线程,它可以通过UI上的按钮启动和停止。GUI应该显示当前时间。我认为GUI和后台线程之间的通信可以通过命令通道完成,通过互斥锁完成计数。在本例中,我省略了通过通道的通信。专注于互斥锁。

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release

use eframe::egui;
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let options = eframe::NativeOptions {
        initial_window_size: Some(egui::vec2(320.0, 240.0)),
        fullscreen: false,
        default_theme: eframe::Theme::Light,
        ..Default::default()
    };
    eframe::run_native(
        "My egui App",
        options,
        Box::new(|_cc| Box::new(Timer::default())),
    );
}

struct Timer {
    time: u32,
    counter: Arc<Mutex<i32>>,
}

impl Default for Timer {
    fn default() -> Self {
        let counter = Arc::new(Mutex::new(0));
        let counter_clone = Arc::clone(&counter);

        //spawn looping thread
        let _ = thread::spawn(move || {
            loop {
                let mut num = counter_clone.lock().unwrap();
                *num += 1;
                std::thread::sleep_ms(100);
            }
        });

        Self {
            time: 0,
            counter: counter,
        }
    }
}

impl eframe::App for Timer {
    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ctx, |ui| {
            let mut num = self.counter.lock().unwrap();

            ui.heading(format!("My egui Application {}", num));
        });
    }
}

这编译和运行,但它是超级滞后。你能帮助我了解我可以做得更好吗?

fiei3ece

fiei3ece1#

在睡眠循环中,在整个睡眠期间保持锁。

loop {
    let mut num = counter_clone.lock().unwrap();
    *num += 1;
    std::thread::sleep_ms(100);
} // counter_clone only gets released here.

您可以在增加数字后添加对drop的手动调用:

loop {
    let mut num = counter_clone.lock().unwrap();
    *num += 1;
    drop(num); // counter_clone now gets released here before we wait.
    std::thread::sleep_ms(100);
}

或者只需lock即可:

loop {
    *counter_clone().lock.unwrap() += 1; // counter_clone gets unlocked at the end of this statement.
    std::thread::sleep_ms(100);
}

相关问题