Qt中线程之间的通信

时间:2012-05-31 08:18:38

标签: qt signals-slots qthread

我正在使用C ++ / Qt中的线程,每个线程都要建立并保留QTcpSocket连接。

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

我的第一个想法是将每个线程传递给一个类,在那里我可以存储每个线程状态并检查其他人的。

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

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

这可能与否?

2 个答案:

答案 0 :(得分:3)

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

你做的是:

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

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

  3. 通过调用{{1>}对象将这些对象移动到一个或多个QThreads。

  4. 如您所见,设置信号插槽连接是以通常的方式完成的,不需要特别注意。 Qt为您完成所有工作,包括在线程之间移动QObject时将连接类型从moveToThread(QThread*)更改为Qt::DirectConnection

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

    1. 将自定义事件发布到QObject,并在派生的QObject的Qt::QueuedConnection方法中处理它。

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

    3. 在先前查找的方法上使用customEvent(QEvent*)。比#4快,因为方法查找只提前一次完成。

    4. 使用QMetaMethod::invoke

    5. 向QObjects发布QEvent比使用信号槽调用更快,因为没有调用复制构造函数,除了在构造QEvent时直接由你完成编组。

      只有在分析/基准测试显示事件发布太慢时,您才会想要使用QMetaObject::invokeMethod。拥有过多的QThread会产生相反的效果,您可能不应该超过系统上的CPU核心数。使用诸如互斥锁或信号量之类的同步原语需要您提交太多线程。你肯定想要每个连接有一个线程! Qt已经为每个QObject提供了一个事件队列互斥锁,方法是使用你已经使用过的事件队列。

答案 1 :(得分:2)

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

如果我是你,我可能会调查QSemaphoreQSharedMemory