我认为 QGraphics* 类不是线程安全的是否正确?我正在将一个旧应用程序移植到 Qt,并在此过程中也试图使其成为多线程。我查看了更新代码,没有看到任何锁。
我一开始是正确的,我所有的处理都是在一组工作线程中完成的,这样 GUI 就不必阻塞。但是,一旦我开始显示我的视觉表示,整个事情就会像一副纸牌一样崩溃,因为更新代码试图从另一个线程正在写入的缓冲区中读取数据。
这是我的测试用例:
- 创建一堆椭圆对象
- 创建一个线程并将场景指针传递给它
- 在循环中修改场景中任何对象的任何设置。
测试函数:
bool CBasicDocument::Update( float fTimeStep )
{
const QList<QGraphicsItem*> tObjects = items();
for( QList<QGraphicsItem*>::const_iterator tIter = tObjects.constBegin();
tIter != tObjects.constEnd();
++tIter )
{
QGraphicsEllipseItem* pElipse = (QGraphicsEllipseItem*)(*tIter);
if( pElipse )
{
pElipse->setPen( QPen( QColor( (int)(255.0f * sinf( fTimeStep )), (int)(255.0f * cosf( fTimeStep )), (int)(255.0f * sinf( fTimeStep )) ) ) );
}
}
return true;
}
我一直在考虑解决这个问题的方法,但没有一个特别漂亮。
理想情况下,我希望发生的情况是,当我更改一个对象的设置时,它会缓冲到下一次渲染调用,但暂时我会解决它而不是崩溃!
目前我有四个选择:
对整个场景进行双缓冲,保持两个场景图同步(一个渲染,一个更新)。这就是我们的多线程游戏引擎的工作方式。这在这里很可怕,因为它需要双倍的 CPU 时间和双倍的内存。更不用说维护两个场景图的后勤工作了。
将 QGraphics* 修改为线程安全的,如上。这可能是最实用的方法,但要完成它需要大量工作。
将对场景的修改推送到队列中并从主线程处理它们。
暂时放弃多线程,让我的应用程序在文档更新时停止。 (考虑到某些文档的数据大小,这不是很好)
它们都不是特别吸引人,都需要大量的工作。
以前有没有人有任何想法或尝试过多线程 QGraphicsScene?
干杯
最佳答案
我一直读到,无论您使用的是 GTK、Qt 还是其他,让所有 GUI 工作都在主线程中进行是一个更好的主意。
在你的情况下,我会选择选项 2。
修改 Qt 的代码以在此处加锁,这是 ihmo 最糟糕的做法,因为如果不进行大量工作,您将无法将修改后的 Qt 与上游同步。
关于c++ - QGraphicsView/Scene - 多线程噩梦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1800349/