开发者

QThread won't stop / does not process a signal

I am trying to perform some work in a separate thread and stop that thread when the work is done.

I have set up a connection like this

thread.connect( workerClass, SIGNAL( finished() ), SLOT( quit() ) );

but the quit() slot is never called when I emit the finished() signal. The command line does not show any warnings related to failed connections.

I created a simple test project to narrow down the problem and I get the same behavior:

TestClass.h:

#ifndef TESTCLASS_H
#define TESTCLASS_H
class TestClass : public QObject
{
    Q_OBJECT
public:
    TestClass() { }
signals:
    void finished();
public slots:
    void doWork();
}
#endif // TESTCLASS_H

TestClass.cpp:

#include "TestClass.h"
#include <QtCore/QDebug>
void TestClass::doWork()
{
    qDebug() << "Starting";
    for( long i = 0; i < 1000000000; i++ );
    qDebug() << "Done";
    emit finished();
};

and the main.cpp:

#include <QtCore/QCoreApplication>
#include <QtCore/QThread>
#include "TestClass.h"

int main( int argc, char* argv[] )
{
    QCoreApplication a( argc, argv );

    TestClass testClass;
    QThread testThread;

    testClass.moveToThread( &testThread );

    testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );
    testClass.connect( &testThread, SIGNAL( started() ), SLOT( doWork() ) );

    testThread.start();
    testThread.wait();

    return 0;
}

So here is what I expected to happen:

  1. Once testThread.start() gets processed, the thread's run() function gets called, which internally calls exec() and starts an event loop. Additionally it 开发者_StackOverflowthrows a started() signal.
  2. testClasshas its doWork() slot called.
  3. When TestClass::doWork() is done, it throws a finished() signal.
  4. The event loop of testThread receives the signal and forwards it to its quit() slot
  5. testThread.wait() returns from waiting as the thread has ended.

Steps 1-3 work and I get the qDebug() output. The problem is at step 4: The signal is fired and forwarded to some event loop (I debugged it a bit, but couldn't figure out to which event loop it was fired) but the quit() slot is never called.

What am I doing wrong?

P.S.: Please don't suggest subclassing QThread instead, the whole point of me trying this way out is because I want to avoid subclassing QThread.


I believe the issue is that you actually don't have Qt event loop running in the scenario. If you replace testThread.wait() with a.exec() (which starts the Qt event loop) you should see your signals/slots getting processed properly.

If you want the application to quit when your thread has finished you can use QCoreApplication's quit() slot to do so.


I had the same problem and found the answer. Here is my question: What is the use of QThread.wait() function?

To solve your problem, you don't need to run the a.exec(), what you need to do is, instead of invoking the quit() which tries to send a signal to your application's event loop (which apparently doesn't exist), you have to call it directly.

So for your code, drop the line:

testThread.connect( &testClass, SIGNAL( finished() ), SLOT( quit() ) );

And instead of:

emit finished();

Use:

this->thread()->quit();

Tada... problem solved. Lesson learned: don't try to exit a worker thread by the qt signal-slot mechanism from within it, because your signals do not end up where they are supposed to (your worker thread's event loop), but they end up in the creating thread instead. You never know what that thread is doing, and if its event loop is running or not, and this shouldn't be of business to your worker thread anyways... Instead, call the quit directly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜