在我的GUI中,我在主窗口中有一个列表存储树视图。当用户双击一行时,弹出一个对话框。问题是我在对话框中填充的数据需要一段时间来处理,所以我所做的是启动一个线程(使用boost线程)来执行对话框计算。GTK中线程的死锁问题
In main:
.......
g_signal_connect (G_OBJECT (m_treeview), "row_activated", G_CALLBACK (m_row_activated),
(gpointer) main_window);
.......
In m_row_activated:
.........
// combo_box and dialog are GtkWidget* global variables
create_dialog(dialog, combo_box); // function creates the combobox
set_combo_box_with_loading_message;
gtk_widget_show_all (dialog);
thread m_thread (bind (&do_dialog_calculations, data1, data2, combobox));
.........
In do_dialog_calculations:
.........
// do_calculations takes about 15 seconds to complete
do_calculations(MyData data1, MyData data2, combobox);
gdk_threads_enter();
gtk_combo_box_append_text(...);
gdk_threads_leave()
一切工作正常(即当用户双击一排,一个对话框的加载消息立即弹出,并最终被填充在线程返回时),但我的问题是当用户关闭该对话框do_dialog_calculations中的do_calculations完成之前。如果对话框被销毁,我的组合框内的组合框将被销毁,并且我对gtk_combo_box_append_text的调用将会发生故障。
我试图更新前测试组合框:
In do_dialog_calculations:
.........
do_calculations(MyData data1, MyData data2, combobox);
gdk_threads_enter();
if (GTK_IS_COMBO_BOX (combobox))
gtk_combo_box_append_text(...);
gdk_threads_leave()
但这会导致死锁在调用GTK_IS_COMBO_BOX。我认为这是GTK_IS_COMBO_BOX可能调用gdk_threads_enter()的原因。我也尝试过测试NULL
if (combobox == NULL)
但这似乎并不奏效。有关如何解决此问题的任何建议?
更新:在GTK_IS_COMBO_BOX发生死锁时,如果我在打开对话框后立即关闭对话框(即在do_calculations()之前完成),如果我只是让对话框坐下来,它最终会更新;另外,如果我切换组合框写调用gdk_threads_enter()之前。
if (GTK_IS_COMBO_BOX (combobox)
{
gdk_threads_enter();
gtk_combo_box_append_text(...);
gdk_threads_leave();
}
当我摧毁的对话框代码执行之前不会发生死锁但是,我怕罕见的可能性GTK_IS_COMBO_BOX检查完成后,用户将关闭对话框。
PS - 我使用线程来做我的对话框计算,因为对话框是非模态的,我希望用户能够在对话框填充时用主UI做其他事情。
感谢asveikau快速回复!我在调用gtk_main()之前调用g_thread_init和gdk_threads_init: g_thread_init(NULL); gdk_threads_init(); gtk_init(&的argc,&argv); ....... gdk_threads_enter(); gtk_main()函数; gdk_threads_leave(); 有趣的是,当我破坏GTK_IS_COMBO_BOX之前的对话框,检查死锁只发生。例如,当我双击一行时,弹出对话框(大约15秒后),但是如果我双击该行并立即销毁对话框,它会挂在GTK_IS_COMBO_BOX检查上 – Tim
@Tim - 读你的评论我想我看到了另一个问题,我已经更新了答案。 – asveikau
感谢asveikau为您提供的所有帮助!您的解决方案奏效。 – Tim