PDA

View Full Version : Calling QThread.wait() from mainthread



P@u1
1st June 2011, 16:02
Hello everyone,

I tried code similar to the following (i shortened it a bit):


class WorkerThread : public QThread
{
Q_OBJECT
public:
~WorkerThread();
protected:
void run();
private slots:
void update();
private:
volatile bool m_isInterrupted;
};
WorkerThread::~Workerthread()
{
m_isInterrupted = true;
wait();
}
void WorkerThread::run()
{
QTimer * timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(update()));
timer->start(80);
exec();
}
void WorkerThread::update()
{
if(m_isInterrupted)
{
quit();
}
//do something
}


The wait() call is needed to prevent the main thread from deleting the workerThread object, while it is still running...

Note: I tested it with slightly different code, so I'm not 100% sure if the following statements are accurate, but I think so:
When closing the application, the process does not terminate and the quit() method is never called, which I verified by debugging.

I think this happens because when the mainthread calls wait() somehow the workingthread's event queue is not dispatched anymore, but I don't understand why, I thought the workingthread has a different evene queue.

It would be nice if you can explain me, why this happens and how I can fix it.
Alternative solutions for my problem would be nice, too!

Thanks for help in advance!

wysota
1st June 2011, 16:28
The wait() call is needed to prevent the main thread from deleting the workerThread object, while it is still running...
You just need to tell the thread to quit() before you start deleting it.

joyer83
1st June 2011, 16:38
Remember that slots are always called by that thread where the slot's object lives.

So, in your case you have probably created the WorkerThread in the main thread and then you have started it with start()


// executing in main thread
worker = new WorkerThread; // created in main thread so it lives in it too
worker->start();
Now, when timeout() signal is emitted in the worker thread the main thread would call the update() slot if the execution would be inside the event loop. But, since the execution is currently blocked inside the wait() call, nothing happens.

To fix this, the WorkerThread object would need to live in the worker thread.

I'll modify your class a bit:


class Worker : public QObject
{
Q_OBJECT
public:
~Worker();
private slots:
void run();
void update();
private:
volatile bool m_isInterrupted;
};
Then in main thread where you created the worker:


// executing in main thread
thread = new QThread;
worker = new Worker; // created in main thread so it lives in it too
worker->moveToThread( thread ); // change thread where the worker lives
thread->start();
QTimer::singleShot( 0, worker, SLOT(run()) ); // ask 'thread' to call the run() slot

P@u1
1st June 2011, 16:41
You just need to tell the thread to quit() before you start deleting it.

Thats exactly what i'm trying.
I set a flag which causes the thread to call quit, but it will need a short time until the thread does that and i must wait until it has been done so i use wait().

But unfortunately my approach causes the mentioned problems.
It would be nice if you can provide some code.
Thanks in advance.

Edit: just as a note: while i was writing this there was another post
@joyer83: thx for help! I will try this.