我正在使用 gtk-rs 创建一个 UI 应用程序。在应用程序中,我必须生成一个线程来持续与另一个进程通信。有时,我需要根据该线程中发生的情况更新 UI。但是,我不确定如何做到这一点,因为我无法跨线程持有对 UI 的任何部分的引用。以下是我尝试的代码:
这很有道理,我可以理解Gtk小部件不是线程安全的。但是那么该如何更新它们?是否有一种安全地向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: >k::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(
循环的方法?无论我采取哪种解决方案,都必须具有非常高的性能。我将发送比示例中更多的数据,并希望刷新屏幕的延迟非常低。
谢谢您的帮助!