无法在QThread与多个Qthread的finished()信号之间进行连接

Joh*_*ang 4 c++ qt multithreading qthread

我有一个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; }
Run Code Online (Sandbox Code Playgroud)

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; }
Run Code Online (Sandbox Code Playgroud)

Thread3类:

void
Thread3::run
{
    // some execution
    QMutexLocker ml(&mMutex);
}
Run Code Online (Sandbox Code Playgroud)

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

谁能告诉我哪里可能做错了?

thu*_*uga 6

首先,您应该注意默认的连接类型是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 :: exec()QThread::run(),但请注意,插槽将在QThread对象所在的线程中执行,而不是在它管理的线程中执行.因此,您不应在QThread子类中使用插槽.您应该创建一个QObject子类并将其移动到一个线程.

另一种选择是Qt::DirectConnection在将信号连接到插槽时用于连接类型.