Qthread and movetothread
-
Hello,
below are 2 classes - Worker contains the job to be done. startThread in Starter creates the new thread and moves the doWork-Method to the new thread.
I don't understand, why the wait call in startThread never returns, when *AutoConnection *or *QueuedConnection *is used. (in the connect-call) Only if *DirectConnection *is used, the debug message after wait appears.
If I understand it right, DirectConnection should not be used in this example. Because doWork runs in a different thread.
In the example qt 4.8.1 is used.
Please, can somebody help?
@#ifndef WORKER_H
#define WORKER_H#include <QObject>
#include <QDebug>
#include <QThread>class Worker : public QObject
{
Q_OBJECT
public:
Worker();
signals:
void finished();
public slots:
void doWork()
{
for (int i = 0; i < 5; i++)
{
qDebug() << "hello world" << QThread::currentThreadId();
}
emit finished();
}
};#endif // WORKER_H@
@#ifndef STARTER_H
#define STARTER_H#include <QObject>
#include <QThread>
#include <QDebug>#include "worker.h"
class Starter : public QObject
{
Q_OBJECT
public:
Starter();void startThread() { Worker w; QThread t; w.moveToThread(&t); connect(&t, SIGNAL(started()), &w, SLOT(doWork()), Qt::DirectConnection); connect(&w, SIGNAL(finished()), &t, SLOT(quit()), Qt::DirectConnection); t.start(); qDebug() << "start"; t.wait(); qDebug() << "ende"; }
};
#endif // STARTER_H@
-
What do you want to do? Do you want to have "hello world" before "start"?
-
no, I want an "ende" message.
If I use Qt::QueuedConnection or Qt::AutoConnection the "ende" message is never displayed. The program waits in "t.wait" forever.
I don't understand why.
-
You are running a standard QThread and did not overwrite the run() method. That is okay. It's actually how they recommend using QThread nowadays. However you need to be aware that the default implementation of QThread::run() will run an Event Loop and thus won't exit until QThread::quit() has been called. As you never call that function, QThread::run() never terminates. It happily continues event processing and you will wait forever.
Instead of waiting synchronously inside startThread(), you might simply connect the Worker's finished() Signal to some other Slot of your Starter class. Whatever needs to be done when the worker has finished, you could to it there. But if you absoloutely need to wait in a synchronous way, you might replace "t.wait()" with:
@QEventLoop loop;
connect(&w, SIGNAL(finsihed()), &loop, SLOT(quit()));
loop.exec(QEventLoop::ExcludeUserInputEvents);@ -
It's a not very good solution cause when you start doWork you can't stop it till it finished.
You can try to modify your example by starting your work with singleshot timer after thread is started.@QTimer::singleShot(0, w, SLOT(doWork());@
and remove
@connect(&t, SIGNAL(started()), &w, SLOT(doWork()), Qt::DirectConnection);@Also, as I understand, you should use auto or queued connection here, cause worker and thread are in different threads.
@connect(&w, SIGNAL(finished()), &t, SLOT(quit()));@