4

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

线程1类:

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; }

线程2类:

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; }

线程3类:

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

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

谁能告诉我哪里做错了?

4

1 回答 1

7

首先,您应该注意默认连接类型是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 个线程的情况下,thread1object 会存在于主线程中,thread2object 会存在于 object 管理的线程中thread1,并且因为那里没有正在运行的 event loop,所以thread2object 中的 slot 永远不会被执行。

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

Qt::DirectConnection当您将信号连接到插槽时,另一个选项是用于连接类型。

于 2013-10-15T06:34:36.207 回答