信号/时隙多线程Qt

时间:2017-07-02 17:58:37

标签: c++ multithreading qt signals-slots

我知道这是关于线程之间的连接信号/插槽机制的下一个问题。我写了Worker申请工作。

主要问题

我有一个已被移动到另一个线程的worker类。应用程序的第二部分是带按钮的GUI界面。当我点击按钮线程开始时:

void MainWindow::startStopThreadA()
{
    ...
    else
    {
        threadA = new QThread;
        workerA = new WorkerObject;
        workerA->setMessage("Thread A running");
        workerA->moveToThread(threadA);

        connect(threadA, SIGNAL(started()), workerA, SLOT(process()), Qt::QueuedConnection);
        connect(workerA, SIGNAL(finished()), threadA, SLOT(quit()));
        connect(workerA, SIGNAL(finished()), workerA, SLOT(deleteLater()));
        connect(threadA, SIGNAL(finished()), threadA, SLOT(deleteLater()));
        //Connect signal from thread with slot from MainWindow
        connect(workerA, SIGNAL(printMessage(QString)), this, SLOT(printMessage(QString)), Qt::QueuedConnection);

        threadA->start();
        ui->threadAButton->setText("Stop A");
    }
}

线程启动时会发出信号:

void WorkerObject::process(void)
{
    //Infinity thread loop
    forever
    {
        //Exit loop part
        mutex.lock();
        if(m_stop)
        {
            m_stop = false;
            mutex.unlock();
            break;
        }
        mutex.unlock();

        //Hold/unhold loop part
        mutex.lock();
        if(!m_hold)
        {
            mutex.unlock();
            //Here signal is emited
            emit printMessage(messageStr);          //That not works
            //qDebug() << "Thread A test message."; //That works properly
        }
        mutex.unlock();
    }
    emit finished();
}

在主GUI线程中,我有用于显示GUI线程工作的计时器。所以qDebug()工作正常并从我的线程打印消息。 GUI线程中的计时器工作正常,并在textEdit GUI字段内打印消息。

现在发出printMessage信号时,GUI线程执行插槽方法:

void MainWindow::printMessage(QString str)
{
    ui->textEdit->append(str);
}

这是我问题中最重要的部分:

当来自printMessage对象的信号workerA与GUI插槽printMessage连接Qt::QueuedConnection 时,我的应用程序挂起。没有可能点击某个按钮甚至退出应用程序。

当信号/插槽与Qt::BlockingQueuedConnection连接时,一切正常。消息在线程之间发送和接收,GUI计时器工作正常。

所以我的问题是为什么连接Qt::QueuedConnection会导致该应用冻结?

1 个答案:

答案 0 :(得分:0)

我用@ m7913d帮助解决了这个问题。

  

您可以尝试在永久循环中执行QThread :: sleep(f.e。   1秒)检查它是否能解决您的问题。

因此工人的线程太频繁地发出信号。在发出信号后添加QThread::msleep(5)确实有帮助。还需要包括在内。