gtk-rs:如何从另一个线程更新视图

问题描述

我正在使用 gtk-rs 创建 UI 应用程序。在那个应用程序中,我必须生成一个线程来与另一个进程持续通信。有时,我必须根据该线程中发生的情况更新 UI。但是,我不确定如何执行此操作,因为我无法跨线程保存对 UI 任何部分的引用。

这是我试过的代码:

use gtk;

fn main() {
    let application =
        gtk::Application::new(Some("com.github.gtk-rs.examples.basic"),Default::default()).unwrap()

    application.connect_activate(|app| {
        let ui_model = build_ui(app);
        setup(ui_model);
    });

    application.run(&[]);
}

struct UiModel { main_buffer: gtk::TextBuffer }

fn build_ui(application: &gtk::Application) -> UiModel {
    let glade_src = include_str!("test.glade");
    let builder = gtk::Builder::new();
    builder
        .add_from_string(glade_src)
        .expect("Couldn't add from string");

    let window: gtk::ApplicationWindow = builder.get_object("window").unwrap();
    window.set_application(Some(application));
    window.show_all();

    let main_text_view: gtk::TextView = builder.get_object("main_text_view")

    return UiModel {
        main_buffer: main_text_view.get_buffer().unwrap(),};
}

fn setup(ui: UiModel) {
    let child_process = Command::new("sh")
        .args(&["-c","while true; do date; sleep 2; done"])
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    let incoming = child_process.stdout.unwrap();

    std::thread::spawn(move || {                              // <- This is the part to pay
        &BufReader::new(incoming).lines().for_each(|line| {   //    attention to.
            ui.main_buffer.set_text(&line.unwrap());          //    I am trying to update the
        });                                                   //    UI text from another thread.
    });
}

但是,我收到错误:

    |       std::thread::spawn(move || {
    |  _____^^^^^^^^^^^^^^^^^^_-
    | |     |
    | |     `*mut *mut gtk_sys::_GtkTextBufferPrivate` cannot be sent between threads safely

这是有道理的。我可以理解 Gtk 小部件不是线程安全的。但是我该如何更新它们呢?有没有办法安全地向 UI 线程发送信号?或者有没有办法以不阻塞 UI 的方式在同一线程中运行 .lines().for_each( 循环?

无论我采用哪种解决方案,都必须具有非常高的性能。我将发送比示例中更多的数据,我希望屏幕刷新延迟非常低。

感谢您的帮助!

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)