QTh读取传入和传出数据

QThread passing data to and from

本文关键字:数据 读取 QTh      更新时间:2023-10-16

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

我有这个函数,它在从类主窗口的主线程单击按钮时运行:公共 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我做了一个结构体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 冻结。过程是这样的:

  • 图形用户界面冻结
  • 线程 1 中的事情完成
  • 线程 1 中的事情再次完成
  • 线程 2 中的事情完成
  • 线程 2 中的事情再次完成
  • 图形用户界面解冻

知道为什么吗?

编辑2:

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

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

由于您使用的是QThread,因此您可以通过使用Qt的线程安全插槽和信号机制来避免显式使用互斥锁等。 基本上,您需要发送到线程的数据打包到一个对象中,然后发出一个以该对象作为参数的信号。 线程将在插槽(您之前连接到信号)中接收该对象的副本,然后开始使用数据。 要将数据从工作线程返回到主线程,您需要反向再次执行相同的操作。 这是一篇包含一些示例代码的文章。

补充一下 Jeremy 的答案:您可以通过在 QObjects 之间发送事件而不是使用信号槽机制来做同样的事情。使用最方便的。

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

启动原始QThread时,run()方法的默认实现将启动事件循环。您会注意到,这样的线程实际上是空闲的,并且不消耗任何 CPU 资源:事件队列为空,事件循环被阻塞,等待某人将事件发布到其队列中。一旦您将一些 QObjects 移动到这样的线程,排队的信号槽交付将通过该线程的事件循环完成。无论是 GUI 线程还是任何其他线程,它的工作方式都相同。在接收事件或排队信号时,GUI 线程在任何方面都不是特别的。