【问题标题】:Unable to connect between QThread with finished() signal for multiple Qthread无法在 QThread 与完成()信号之间连接多个 Qthread
【发布时间】:2013-10-15 14:34:36
【问题描述】:

我有 3 个 QThreads 相互调用(全部继承自 QThread。我知道有些人可能会建议使用 moveToThread,但暂时忽略这个事实)。简化代码如下所示:

Thread1 类:

void
Thread1::run
{
    // some execution
    Thread2 t2 = new Thread2();
    connect(t2,SIGNAL(finished),this,SLOT(onFinished));
    t2->start();

    while(!stop)  // stop was initialized as false
    {
        this->msleep(10);
    }    
}
void Thread1::onFinished(){ stop = true; }

Thread2 类:

void
Thread2::run
{
    // some execution
    Thread3 t3 = new Thread3();
    connect(t3,SIGNAL(finished),this,SLOT(onFinished));
    t3->start();

    while(!stop)  // stop was initialized as false
    {
        this->msleep(10);
    }    
}
void Thread2::onFinished(){ stop = true; }

Thread3 类:

void
Thread3::run
{
    // some execution
    QMutexLocker ml(&mMutex);
}

当我只有两个线程时,它工作得非常好(例如只有 thread2 和 thread3)。在我转移到三线程场景之后,onFinished() 方法似乎不再与 finished() 信号正确连接。 thread2 中的 onFinished() 曾经被调用过。而且我很确定thread3的执行已经完成。

谁能告诉我哪里做错了?

【问题讨论】:

  • 我在您发布的部分代码中看不到任何错误。尝试使用qDebug() 来确定@​​987654325@ 是否返回true,以及onFinished() 插槽是否被实际调用。
  • @TimMeyer,我确实在 onFinished() 处打印了出来,但什么都没有打印出来。基本上程序一直卡在thread2的while循环中。但我很确定 thread3 已经完成,因为我在 run() 方法的末尾还有一个调试打印输出。

标签: c++ multithreading qt qthread


【解决方案1】:

首先你应该注意默认的连接类型是Qt::AutoConnection。这意味着如果信号是从与接收对象线程不同的线程发出的,则使用Qt::QueuedConnection。在这种情况下:The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread. 所以你需要一个事件循环。

它适用于 2 个线程,因为您可能在主线程中运行了一个事件循环。在您仅使用thread2thread3 对象的情况下,thread2 对象实际上将存在于主线程中,而thread3 对象将存在于由thread2 对象管理的线程中。所以thread2 对象中的插槽应该可以工作。

但是在 3 个线程的情况下,thread1 对象将存在于主线程中,thread2 对象将存在于由thread1 对象管理的线程中,并且因为那里没有运行事件循环,所以插槽thread2 中的对象永远不会被执行。

您可以在QThread::run() 函数中调用QThread::exec(),但请注意,插槽将在您的QThread 对象所在的线程中执行,而不是在它管理的线程中执行。因此,您不应该在QThread 子类中使用槽。您应该创建一个QObject 子类并将其移至线程。

当您将信号连接到插槽时,另一种选择是使用 Qt::DirectConnection 作为连接类型。

【讨论】:

  • 感谢您的解释! Qt::DirectConnection 似乎解决了这个问题。当您说“创建 QObject 子类并将其移动到线程”时,您是指使用 moveToThread 方法吗?我可能会尝试这种方法,因为我正在修改 onFinished() 方法中的一些变量,所以我担心 Qt::DirectConnection 可能是一个问题?
  • @JohnYang 是的,我是。对于Qt::DirectConnection,它就像一个直接的函数调用。
猜你喜欢
  • 2015-11-30
  • 1970-01-01
  • 2018-03-13
  • 1970-01-01
  • 1970-01-01
  • 2014-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多