通过不同的线程使用QTcpSockets

时间:2016-03-17 15:39:24

标签: c++ multithreading qt qt5

以下情景:

我在主线程中创建了一些QTcpSockets并将对象保存在单例(std::vector<QTcpSocket*>和getter中)中;如果用户按下&#34; StartMeasure&#34;按钮我启动一个新线程,以避免在GUI中阻止行为!

我再次开始n个用于硬件通信的新线程(由于速度原因需要并行流) - &gt;发送/接收内容并评估响应。 (使用getter到存储在单例中的QTcpSockets)

主题模型:

Thread Model

如果我这样做,我收到了这个警告:

QSocketNotifier: socket notifiers cannot be enabled/disabled from another thread

有时这个错误:

_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)

我是否也应该在线程之间使用QTcpSockets上的信号工作,或者我该如何解决这个问题? (不想发布代码,因为我只需要一个策略/提示如何正确执行)

谢谢!

2 个答案:

答案 0 :(得分:2)

要在Qt中实现线程间交互,您可以使用以下技术之一。

首先,您可以在具有Qt::QueuedConnectionQt::AutoConnection属性的单独线程中简单地连接QObjects livinig的信号和插槽。然后,Qt将使用自己的事件循环系统将一个线程中的信号提升到其他线程中的插槽。

其次,您可以使用QMetaObject::invokeMethodQt::QueuedConnectionQt::AutoConnection从一个线程调用到其他线程中的QObject。 Qt将再次在另一个主题中宣传调用调用。

实际上你不能直接从网络对象的一个​​线程方法(例如QTcpSocket),QTimers和其他使用Qt事件循环系统的其他线程中调用并存在于其他线程中。

<强>更新

请注意,只有当目标线程中有QEventLoop运行时,上述注意事项才适用(不确定,可能是信号/插槽适用于两个线程都必须使用它)。如果您未在重写QThread中重新实现run()或手动调用exec(),则run()会默认提供一个。

答案 1 :(得分:1)

根据我在一个线程中创建QT套接字以及从另一个线程读取/写入它们的经验不是一个好主意,因为您可能遇到多个问题,例如您获得的问题和崩溃。我建议你在你将使用它们的线程中实际实例化套接字(调用构造函数)。另一个似乎不太好的想法是在一个线程中实例化套接字并移动到另一个线程。虽然它通常适用于其他类,但由于某些内部和可能的系统实现,这显然不能100%正确地完成套接字。所以我遇到了崩溃,特别是当我尝试删除套接字时,甚至是异步(使用deleteLater)并使用线程同步,这是由在已删除套接字上调用的readyRead引起的。

因此,请考虑更改您的体系结构以在您使用它们的线程中创建/删除套接字,甚至避免在另一个线程中存储指针(智能和原始)(至少不依赖于它们的有效性)。

我希望这些提示可以帮助您避免我对套接字和多线程的痛苦。