QThread emit resultReady can't trigger slot



  • example address
    http://doc.qt.io/qt-5/qthread.html

    i create one console project. the whole code as follow.

    //main.cpp
    #include <QCoreApplication>
    #include <QTimer>
    #include "task.h"
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
    
        Task * task = new Task( &a);
    
        QObject::connect( task, SIGNAL(finished()), &a, SLOT(quit()));
    
        QTimer::singleShot( 0, task, SLOT(run()));
    
        return a.exec();
    }
    
    //task.h
    #ifndef TASK_H
    #define TASK_H
    
    #include <QObject>
    
    class Task : public QObject
    {
        Q_OBJECT
    public:
        Task(QObject *parent = 0) : QObject(parent) {}
    
    public slots:
        void run();
    signals:
        void finished();
    };
    
    #endif // TASK_H
    
    //task.cpp
    #include "task.h"
    #include <QPointer>
    #include <iostream>
    #include "controller.h"
    
    QPointer<Controller> ptrControl = 0;
    void Task::run()
    {
        char input[128];
        while( true){
    
            std::cout << "please input \r\n";
            std::cin >>input;
            QString qStrInput;
            qStrInput = input;
            if( qStrInput == "exit"){
                if( ptrControl){
                    ptrControl->deleteLater();
                }
                break;
            }
            else if( "new" == qStrInput ){
                if( ptrControl == 0){
                    ptrControl = new Controller();
                }
                continue;
            }
            else if( "test" == qStrInput ){
                if( ptrControl){
                    ptrControl->MyTest();
                }
                continue;
            }
        }
    
        emit finished();
    }
    
    //controller.h
    #ifndef CONTROLLER_H
    #define CONTROLLER_H
    
    #include <QObject>
    #include <QThread>
    #include <QDebug>
    #include "worker.h"
    
    
    class Controller : public QObject
    {
        Q_OBJECT
        QThread workerThread;
        public:
            Controller() {
                Worker *worker = new Worker;
                worker->moveToThread(&workerThread);
                connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
                connect(this, &Controller::operate, worker, &Worker::doWork);
                connect(worker, &Worker::resultReady, this, &Controller::handleResults);
                workerThread.start();
            }
            ~Controller() {
                workerThread.quit();
                workerThread.wait();
            }
        public slots:
            void handleResults(const QString & r){
                QString tx = r;
                qDebug() << tx;
            }
        signals:
            void operate(const QString &);
    public:
            void MyTest(){
                emit operate( "test...");
            }
    };
    
    #endif // CONTROLLER_H
    
    // worker.h
    #ifndef WORKER_H
    #define WORKER_H
    
    #include <QObject>
    
    class Worker : public QObject
    {
        Q_OBJECT
    
        public slots:
            void doWork(const QString &parameter) {
                QString result;
                result = parameter;
                /* ... here is the expensive or blocking operation ... */
                emit resultReady(result);
            }
    
        signals:
            void resultReady(const QString &result);
    };
    
    #endif // WORKER_H
    
    

  • Moderators

    @changtj This is the main thing you must remember: A while(true) loop blocks the event loop, so your main thread cannot process any signals from other threads. Do not mix infinite loops with signals and slots.

    Your Worker object emits the Worker::resultReady() signal, but the slot in the main thread cannot run until your while loop stops.



  • @JKSH

    yes, it is what you said.
    when i change "while( true)" to "if (true)", it is ok.
    How can i get one "user loop input " application? thanks a lot.


  • Moderators

    @changtj said in QThread emit resultReady can't trigger slot:

    How can i get one "user loop input " application?

    Choose one thread to run your "user loop". This thread should not run an event loop, which means it should not receive any signals. However, it can still emit signals.

    Notes:

    • QCoreApplication::exec() starts an event loop. This prepares your main thread to receive signals.
    • By default, QThread::start() calls QThread::exec() in the new thread. This prepares your new thread to receive signals. (This also allows your Worker Objects to have Slots that run in that thread)
    • To create a thread that doesn't run an event loop, don't use the Worker Object approach. Instead, you can subclass QThread and reimplement QThread::run(), or use QtConcurrent::run(), or use std::thread.

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.