0

我将尝试解释我的程序曾经做什么以及我想要改变什么:

我有这个函数,它在 MainWindow 类的主线程中单击按钮运行: public QMainWindow :

该函数如下所示,并在另一个文件中指定:

void MakeMeshStructure(MeshStructureLayers layers,
                      Handle_AIS_InteractiveContext theContext,
                      Handle_TDocStd_Document aDoc,
                      MyMesh &mesh,
                      int detail_vertex,
                      double insulation_thickness,
                      OpenMesh::VPropHandleT<MyMesh::Scalar> _max_beam_offset);
}

它的作用是:它适用于网格并为网格的每个顶点、面和边缘创建几何图形。此几何图形与上下文一起显示。这个过程需要很长时间(30 分钟)并且会阻塞 gui。

我想做的是拥有与 QThread::idealThreadCount() 一样多的线程,并在计算时释放 gui 并使其更快。(这是正确的想法吗?)

我想将我的网格分成相等的部分,并将这个顶点范围传递给我的函数(上图),以便仅使用一个顶点范围来实现单独的胎面。

我很难弄清楚如何传递这些数据并使其成为线程安全的。我知道它有很多代码,但这是我解决它的尝试:

http://pastebin.com/u/mzagar

问题是以正确的方式获取所有数据并让线程工作。我必须在哪里使用互斥锁。在主线程工作时可以写入的每个数据上?很困惑。泰

编辑:

我编辑了我的代码:http : //pastebin.com/u/mzagar 我制作了一个 struct cadData 来传递数据。这就是我启动线程的方式:

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
 //...
emit startMake1(aCadDatas.at(0));
 //...

问题是线程似乎不能同时工作,而且 gui 也冻结了。流程如下:

  • GUI 冻结
  • 线程 1 中的事情完成
  • 线程 1 中的事情再次完成
  • 线程 2 中的事情完成
  • 线程 2 中的事情再次完成
  • ...
  • GUI 解冻

任何想法为什么?

编辑2:

我通过将其移至类构造函数来删除同一线程的多次运行:

connect(this, SIGNAL(startMake1(cadData)), cThreads.at(0), SLOT(MakeMesh(cadData)));
//...
cThreads.at(0)->moveToThread(threads.at(0));
//...
threads.at(0)->start();
4

2 回答 2

2

由于您使用的是 QThread,因此您可以通过使用 Qt 的线程安全槽和信号机制为您完成工作,从而避免显式使用互斥锁等。您基本上会将需要发送到线程的数据打包到一个对象中,然后发出一个以该对象作为参数的信号。线程将在插槽中接收该对象的副本(您之前已连接到您的信号),然后开始使用数据。要将数据从工作线程取回主线程,您需要反过来做同样的事情。 是一篇带有一些示例代码的文章。

于 2012-06-25T19:54:31.787 回答
0

添加到杰里米的答案:您可以通过在 QObjects 之间发送事件而不是使用信号槽机制来做同样的事情。使用对您最方便的。

关键是利用 Qt 的内置事件循环互斥锁。当您向与发送者不同的线程中的对象发送信号时,信号将转换为 QMetaCallEvent 并发布到接收 QObject 的事件队列中。当然,这是以线程安全的方式完成的,所要做的就是利用它。发送显式事件的工作方式相同。在接收者所在的线程中旋转的事件循环只是获取 QMetaCallEvents 并相应地执行插槽调用,或者将您的事件分派给您的customEvent()方法实现。

当您启动 rawQThread时,该run()方法的默认实现会启动一个事件循环。您会注意到这样的线程实际上是空闲的并且不消耗任何 CPU 资源:事件队列是空的,并且事件循环被阻塞,等待有人将事件发布到它的队列中。一旦将一些 QObject 移动到这样的线程,排队的信号槽传递将通过该线程的事件循环完成。无论是 GUI 线程还是任何其他线程,它的工作原理都是一样的。在接收事件或排队信号时,GUI 线程在任何方面都没有什么特别之处。

于 2016-08-10T20:56:57.497 回答