3

我正在使用 C++/Qt 中的线程,每个线程都建立和维护一个 QTcpSocket 连接。

问题是当与网络断开连接时,这些线程必须以特定顺序重新连接。这已经可以了,但是我还有另一个问题:我需要知道每个线程是否只有当前线程已断开连接,或者所有线程都已断开连接。

我的第一个想法是向每个线程传递一个对类的引用,我可以在其中存储每个线程的状态并检查其他人的状态。

但后来我有了一个更简单的想法,我想知道它是否可行或不可能:使用 Qt 的插槽和信号。

因此,我拥有的每个线程都来自同一个类,但将不同的数据传递给了 Ctor。所以想法是在该类中创建一个插槽和一个信号,将它们连接起来并发出传递一个 ID 的信号。然后,每个线程的插槽都会被启动......或者我可能完全错了,唯一启动的插槽将是来自发出信号的同一个线程的插槽。

这可能吗?

4

2 回答 2

4

首先,信号槽连接是在 QObjects 中的信号和槽之间完成的,而不是在线程之间。好吧,QThread 是一个 QObject,但你真的不应该从 QThread 派生。不要从 QThread 派生,你会没事的。

你要做的是:

  1. 启动一个或多个 QThreads (不仅仅是构造)。那些 QThreads 只是 Qt 的基类,不要从它们派生。一个启动的原始 QThread 被阻塞,等待一个事件被发布到它的事件队列中。QThread::run()调用的默认实现QEventLoop::exec()(或等效的)。因此,这些线程在启动后不会消耗任何 CPU 周期。

  2. 实例化一堆 QObject。根据需要进行所有信号/插槽连接。

  3. 通过调用这些对象将它们移动到一个或多个 QThread moveToThread(QThread*)

如您所见,设置信号槽连接以通常的方式完成,不需要任何特别注意。Qt 为您做所有事情,包括在您在线程之间移动 QObject 时Qt::DirectConnection更改连接类型。Qt::QueuedConnection

请注意,您不能直接在这些 QObjects 上调用任何方法,因为您可能会从不同的线程这样做,因此由于访问未序列化,会发生各种不好的事情。您必须按照从最快到最慢的顺序执行以下任何一项操作,并且仅此一项。请注意,虽然 #3 总是比 #4 快,但您需要在 #2 和 #3 之间进行基准测试,因为它会有所不同。

  1. 将自定义事件发布到 QObject,并在派生的 QObject 的customEvent(QEvent*)方法中处理它。

  2. 使用信号槽连接,并发出连接到 QObjects 槽的信号。

  3. 用于QMetaMethod::invoke先前查找的方法。比 #4 更快,因为方法查找只提前完成一次。

  4. 使用QMetaObject::invokeMethod.

将 QEvents 发布到 QObjects 比使用信号槽调用更快,因为没有调用复制构造函数,并且除了在构造 QEvent 时直接由您完成之外没有编组。

仅当分析/基准测试显示事件发布太慢时,您才想使用QSharedMemory. 拥有过多数量的 QThreads 会适得其反,您应该拥有的 CPU 核心数量可能不超过系统上的数量。天真地使用诸如互斥锁或信号量之类的同步原语需要您提交太多线程。您绝对希望每个连接有一个线程!通过使用您已经使用的事件队列,Qt 已经为每个 QObject 提供了一个事件队列互斥锁。

于 2012-05-31T19:10:31.170 回答
2

信号和槽连接是在运行时完成的,即您正在连接一个类的特定实例。您不能发出信号并将其“广播”到您班级的每个实例。不同线程之间的信号是可能的,但维护它们可能有点麻烦(文档中对此进行了很好的解释)。

如果我是你,我可能会研究QSemaphoreQSharedMemory

于 2012-05-31T11:37:14.330 回答