3

我有一个应用程序可以进行一些模拟并呈现结果。因为渲染有时会很慢,所以我将它分离到另一个线程中,gtk_widget_queue_draw一旦准备好,主线程就会调用。如果还没有完成绘制,额外的请求将被丢弃(因为queue_draw只会使其无效,并且不可能“更多”无效)。

结果是,对于大型复杂系统,模拟最大化一个线程,渲染最大化另一个线程,一切正常。

我刚刚遇到了一个不同的问题,我不明白为什么会这样:足够简单的模拟和渲染(6 条 5 点线)会导致它中断。

前几个步骤(我在任何地方都看到了大约 60 到 400 个)渲染良好(在几分之一秒内),直到一个步骤渲染两次。之后,它会忽略queue_draw, 直到我在渲染窗口上拖动一个窗口,然后它重新启动(直到它再次中断)。

如果我人为地减慢请求(usleep(10000)足够),这不会发生。

然而,这是一个完全不可接受的解决方案,因为不允许显示的过程干扰正常的模拟线程(无延迟,无互斥体等)。我需要一个使渲染线程“尽可能好”的解决方案,因为它正在处理易失性数据。它不必非常准确——我真的不在乎帧渲染是否有一点错误(帧 i 的一半,i+1 的一半很好),只要它确实渲染。

为什么会发生这种情况,我该如何解决?

4

2 回答 2

2

你有一个竞争条件。

从 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*您要绘制的。

gdk_threads_add_idle如果您不确定应用程序使用的库或代码是否使用已弃用(自 3.6 起)和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 调用的锁。

于 2016-04-30T10:11:52.357 回答
0

您是否使用 gdk_threads_enter/gdk_threads_leave 锁定了线程中的 UI 调用?也许添加代码示例也会有所帮助......

于 2012-11-29T00:41:56.850 回答