Why QThread :: ready signal is not emitted?

I created my own TestService , which runs on a separate QThread , but when MainLoop finishes QThread::finished , the signal is not emitted. I saw a similar question , but the problem was a bit different, because the OP was overloaded with QThread , while I was just transferring my class to the stream.

Note that I do not overload the QThread class, I only overload the QObject based on this example: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full -explanation /

Here is my TestService class:

 #include <QObject> #include <QThread> #include <QMutex> #include <QWaitCondition> #include <iostream> using namespace std; class TestService: public QObject { Q_OBJECT; private: volatile int _count; QWaitCondition _monitor; QMutex _mutex; QThread* _thread; public: TestService(int numSeconds) { _count = numSeconds; _thread = NULL; cout << "TestService()" << endl; } virtual ~TestService() { cout << "~TestService()" << endl; } void Start() { QMutexLocker locker(&_mutex); if(_thread == NULL) { _thread = new QThread; // Move this service to a new thread this->moveToThread(_thread); // The main loop will be executed when the thread // signals that it has started. connect(_thread, SIGNAL(started()), this, SLOT(MainLoop())); // Make sure that we notify ourselves when the thread // is finished in order to correctly clean-up the thread. connect(_thread, SIGNAL(finished()), this, SLOT(OnFinished())); // The thread will quit when the sercives // signals that it finished. connect(this, SIGNAL(Finished()), _thread, SLOT(quit())); // The thread will be scheduled for deletion when the // service signals that it finished connect(this, SIGNAL(Finished()), _thread, SLOT(deleteLater())); // Start the thread _thread->start(); } } void Stop() { _count = 0; _monitor.wakeAll(); } private slots: void MainLoop() { cout << "MainLoop() Entered" << endl; while(_count > 0) { cout << "T minus " << _count << " seconds." << endl; QMutexLocker locker(&_mutex); _monitor.wait(&_mutex, 1000); _count--; } cout << "MainLoop() Finished" << endl; emit Finished(); } virtual void OnFinished() { cout << "OnFinished()" << endl; } signals: void Finished(); }; 

Here is the testing code:

 void ServiceTest() { cout << "Press q to quit." << endl; cout << "Press s to start." << endl; cout << "Press t to stop." << endl; QSharedPointer<TestService> testService(new TestService(10)); char in = 'a'; while( in != 'q' ) { switch(tolower(in)) { case 's': testService->Start(); break; case 't': testService->Stop(); break; default: break; } cin.get(in); in = tolower(in); } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); ServiceTest(); QTimer::singleShot(0, &a, SLOT(quit())); return a.exec(); } 

Output:

 Press q to quit. Press s to start. Press t to stop. TestService() s MainLoop() Entered T minus 10 seconds. T minus 9 seconds. T minus 8 seconds. t MainLoop() Finished q ~TestService() Press any key to continue . . . 

Can someone explain why finished not emitted, how can I fix it?

+2
source share
1 answer

The signal completed () is emitted due to a reason, but you will not catch it.

Here:

 connect(_thread, SIGNAL(finished()), this, SLOT(OnFinished())); 

Qt::QueuedConnection used because _thread and this (service) are in different threads.

By the end of the finished() _thread , the _thread event loop is _thread , so the signal will not be delivered to the slot.

You can explicitly use Qt::DirectConnection .

EDIT:

QTherad works as follows:

 QThread::start() { emit started(); run(); emit finished(); } QThread::run() { eventloop->exec(); } 

So, by the time the finished eventloop expires, it will already stop executing. When moving the service to the _thread event loop, the _thread event loop is.

Note that QObject itself does not have its own event loop. Event loops are created by dialog boxes, threads, and the application.


In fact, I would recommend QtConcurent::run in your simple case, since you are not processing the actual events in a new thread, but just run a single function.

+5
source

Source: https://habr.com/ru/post/1446551/


All Articles