QThread emit resultReady can't trigger slot
Unsolved
General and Desktop
-
example address
http://doc.qt.io/qt-5/qthread.htmli 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 ¶meter) { QString result; result = parameter; /* ... here is the expensive or blocking operation ... */ emit resultReady(result); } signals: void resultReady(const QString &result); }; #endif // WORKER_H
-
@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 theWorker::resultReady()
signal, but the slot in the main thread cannot run until your while loop stops. -
@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()
callsQThread::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 useQtConcurrent::run()
, or usestd::thread
.