我有一个应用程序可以进行一些模拟,并呈现结果。因为渲染有时可能非常慢,所以我将它分成另一个线程,主线程准备好后调用gtk_widget_queue_draw
。如果它尚未完成绘制,则额外的请求将被丢弃(因为queue_draw
仅使其无效,并且不可能“更多”无效)。
结果是,对于大型复杂系统,模拟最大化一个线程,并渲染最大化另一个线程,一切正常。
我遇到了一个不同的问题,我不明白为什么会发生这种情况:一个足够简单的模拟和渲染(6个5点线)会导致它崩溃。
前几个(我已经看到从60到400左右的所有地方)步骤渲染得很好(在几分之一秒内),直到一步渲染两次。之后,它会忽略queue_draw
,直到我执行某些操作,例如在渲染窗口上拖动一个窗口,然后重新启动(直到它再次中断)。
如果我人为地减慢了请求(usleep(10000)
已足够),则不会发生这种情况。
然而,这是一个完全不可接受的解决方案,因为不允许显示过程干扰正常的模拟线程(没有延迟,没有互斥等等)。我需要一个解决方案,使渲染线程尽可能“尽可能”,因为它使用的是易失性数据。它不一定非常准确 - 我真的不在乎框架是否有点错误(框架i的一半,i + 1的一半是好的),只要它渲染。
为什么会发生这种情况,我该如何解决?
答案 0 :(得分:1)
你正处于竞争状态。
自GTK3.6 以来,您需要像这样致电gtk_widget_queue_draw
:
g_idle_add((GSourceFunc)gtk_widget_queue_draw,(void*)window);
或者像这样:
gdk_threads_add_idle((GSourceFunc)gtk_widget_queue_draw,(void*)window);
其中window是您要绘制的GtkWidget*
。
如果您不确定应用使用的库或代码是否使用已弃用的(自3.6之后的gdk_threads_add_idle
和gdk_threads_enter
函数,请使用gdk_threads_leave
。
请参阅:https://developer.gnome.org/gdk3/stable/gdk3-Threads.html#gdk3-Threads.description
在GTK3.6之前,必须使用gdk_threads_enter
和gdk_threads_leave
来获取GTK呼叫的锁定。
答案 1 :(得分:0)
您是否使用gdk_threads_enter / gdk_threads_leave锁定了线程中的UI调用? 也许添加代码示例也会有所帮助......