Reputation: 7603
I have a design problem which has been plaguing me for quite some time now. Essentially I have a function which takes long time to execute and a gui which needs to be responsive and up-to-date. When the user hits a start button the long function begins executing in a while loop and after each execution the gui needs to be updated.
I was thinking the best way of doing this was to have a QThread run in a while loop and if the user pressed a start button the long function would begin executing. similar to the following:
class Application : public QThread
{
void run (void)
{
while (!mExiting)
{
if (StartPressed)
LongFunction();
// Need to update gui before
// running long function again
}
}
}
I tried doing QMetaObject::Invoke with BlockingQueuedConnection however, when the gui application quits, the thread gets stuck and never exits. I also tried using a QMutex however, the gui would become locked waiting for the mutex which is locked and in use by the long function.
I was thinking, is there any way to cancel BlockingQueuedConnection when the application wants to quit or is there some other way of implementing this.
Upvotes: 0
Views: 691
Reputation: 98425
You're close, but you don't need to inherit from QThread
. Instead:
Put your computation into a slot in a QObject
.
Put the code that sets the exit flag into another slot (say Q_SLOT void finish();
)
Create an instance of the object. Create an instance of QThread
. Call myObject->moveToThread(myThread)
.
Start the thread.
Connect gui signals to the slots in the computation object, similarly connect signals in the computation object that indicate that the data is ready.
To end the processing and finish the thread, assuming that gui
sends a stop()
signal, set the following connections:
connect(gui, SIGNAL(stop()), myObject, SLOT(finish())
- to stop your computation
connect(gui, SIGNAL(stop()), myObject->thread(), SLOT(quit()))
- to end the event loop in the thread
connect(myObject->thread(), SIGNAL(finished()), myObject->thread(), SLOT(deleteLater())
- to delete the thread when the run()
method returns
You'll still need to delete myObject
when you're done getting the results from it, or at least before your application exits.
Warning: It's an error to delete myObject
if you're doing it from the gui thread and myObject->thread()
is non-zero: you can't delete objects that have thread affinity different than current thread. A zero thread affinity means that no thread claims the object - in our case, when the object's thread is destructed. Then any thread can delete it.
For the same reason, you can't moveToThread
an object that has a parent. The object that you move can have children, though, it just can't have a parent itself.
Upvotes: 1