c++ - QGraphicsView/Scene - 多线程噩梦

标签 c++ multithreading qt qt4

我认为 QGraphics* 类不是线程安全的是否正确?我正在将一个旧应用程序移植到 Qt,并在此过程中也试图使其成为多线程。我查看了更新代码,没有看到任何锁。

我一开始是正确的,我所有的处理都是在一组工作线程中完成的,这样 GUI 就不必阻塞。但是,一旦我开始显示我的视觉表示,整个事情就会像一副纸牌一样崩溃,因为更新代码试图从另一个线程正在写入的缓冲区中读取数据。

这是我的测试用例:

  1. 创建一堆椭圆对象
  2. 创建一个线程并将场景指针传递给它
  3. 在循环中修改场景中任何对象的任何设置。

测试函数:

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;
}

我一直在考虑解决这个问题的方法,但没有一个特别漂亮。

理想情况下,我希望发生的情况是,当我更改一个对象的设置时,它会缓冲到下一次渲染调用,但暂时我会解决它而不是崩溃!

目前我有四个选择:

  1. 对整个场景进行双缓冲,保持两个场景图同步(一个渲染,一个更新)。这就是我们的多线程游戏引擎的工作方式。这在这里很可怕,因为它需要双倍的 CPU 时间和双倍的内存。更不用说维护两个场景图的后勤工作了。

  2. 将 QGraphics* 修改为线程安全的,如上。这可能是最实用的方法,但要完成它需要大量工作。

  3. 将对场景的修改推送到队列中并从主线程处理它们。

  4. 暂时放弃多线程,让我的应用程序在文档更新时停止。 (考虑到某些文档的数据大小,这不是很好)

它们都不是特别吸引人,都需要大量的工作。

以前有没有人有任何想法或尝试过多线程 QGraphicsScene?

干杯

最佳答案

我一直读到,无论您使用的是 GTK、Qt 还是其他,让所有 GUI 工作都在主线程中进行是一个更好的主意。

在你的情况下,我会选择选项 2。

修改 Qt 的代码以在此处加锁,这是 ihmo 最糟糕的做法,因为如果不进行大量工作,您将无法将修改后的 Qt 与上游同步。

关于c++ - QGraphicsView/Scene - 多线程噩梦,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1800349/

相关文章:

c++ - ARM 动态链接

Unity3D上的Java插件无法启动新线程

java - 套接字客户端卡在用户输入上

python - 导入错误 : libOpenGL. so.0:无法打开共享对象文件:没有这样的文件或目录

C++ - 在打印 char* 时指定 std::cout 的最大字符数

c++ - LNK1004 : Cannot open file 'Jsfwbase12D.lib'

c++ - 向后搜索时 libvlc_media_player_set_position 失败

java - 多线程总是比单线程产生更好的性能吗?

javascript - 如何检查 JSON 对象参数是否存在?

qt - TableView 上的 Keys.onPressed 调用了两次