2012-05-31 93 views
2

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

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

我的第一个想法是通过每个线程引用一个类,我将能够存储每个线程状态并检查其他人的。

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

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

这可能吗?

回答

2

信号和插槽连接在运行时完成,即您正在连接某个类的特定实例。你不能发出一个信号并将它“广播”给你的班级的每一个实例。不同线程之间的信号是可能的,但维护它们可能会有点麻烦(这在the documentation中解释得很好)。

如果我是你,我可能会考虑QSemaphoreQSharedMemory

+0

感谢您的链接,我没有找到该文件的信息。我最终使用了互斥锁和共享内存,但我会完全看看线程之间的信号:听起来很有趣。 –

3

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

你要做的就是:

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

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

  3. ,呼吁他们moveToThread(QThread*)将这些对象的一个​​或多个QThreads。

正如您所看到的,设置信号插槽连接按照常规方式完成,不需要特别注意。 Qt会为您执行所有操作,包括在线程间移动QObject时,将连接类型从Qt::DirectConnection更改为Qt::QueuedConnection

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

  1. 邮政自定义事件QObject的,并在派生的QObject的customEvent(QEvent*)方法处理它。

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

  3. 对以前查找的方法使用QMetaMethod::invoke。由于方法查找只提前一次完成,因此速度比#4快。使用QMetaObject::invokeMethod

发布QEvents到的QObject比使用信号槽调用速度更快,因为没有拷贝构造函数调用,并没有在建设QEvent的,除了完成由您直接编组。

只有在性能分析/基准测试显示事件发布速度太慢时,才想使用QSharedMemory来查看。过多数量的QThreads会适得其反,您应该不会超过系统上的CPU内核数量。天真地使用诸如互斥或信号等同步原语需要你提交太多的线程。你绝对是不要想要每个连接有一个线程! Qt通过使用已经使用过的事件队列,每个QObject都有一个事件队列互斥体。