Reputation: 1305
this is the run method of a subclass of QThread:
void crono::Controller::run() {
//initialise timer
int *i = & this->model->seconds_elapsed;
for (*i = 0; *i < this->model->seconds_total; (*i)++) {
//calculate current seconds/minutes/hours elapsed starting from seconds_elapsed (*i)
this->model->tick();
//should display in the form the time elapsed
this->vista->showTime();
sleep(1000);
}
Beep(1000, 500); //beep when all is over
}
the controller updates the model values.
The QT form is opened on start, I guess in the main application thread.
The issue is that despise on debug *i=0 and seconds_total = X > 0, the loop is executed only one time, after the first time the debug halt (it does not end), the forms pops up but nothing happens.
The only thing I can guess of, is that the Controller Thread lose its priority and never gains the cpu again.
How can avoid this?
EDIT I am trying using QTimer, with bad luck.
i declared update as a public slot, and then implemented like this:
void crono::Controller::update() {
this->modello->tick();
this->vista->showTime();
//eventually stop at some point (pointer to timer and timer->stop()?
//...
//Beep(1000, 500);
}
And I inserted the QTimer in the controller (thread) object instead of the loop cycle:
void crono::Controller::run() {
//inizializzo timer
int *i = & this->modello->secondi_trascorsi;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()),this, SLOT(update()));
timer->start(1000);
}
I do not know why, but the update() method is never called, instead of being called an infinite number of times. Why?
Upvotes: 0
Views: 1724
Reputation: 4357
A common confusion is that QThread
runs in its own separate thread. This is not the case; instead, QThread
starts an event loop in a child thread that it controls. QThread
could easily be called QThreadManager
.
In short, don't subclass QThread
, as the functionality you're creating resides in the main thread (not the thread that QThread
handles). Create a QObject subclass with a slot connected to the started()
signal. Then use moveToThread()
and call run()
on your QThread
instance.
Also, you can't directly call main thread functions from a child thread. You'll need a queued connection signal to an object in the main thread to show the dialog box.
Upvotes: 6
Reputation: 929
As Tim Meyer pointed out in his comment, you need to call QThread:exec()
at the end of your QThread::run()
implementation, this in order to start the thread's event loop, which is needed in order for the Signal/Slot mechanism to work.
However, it seems like you're doing it wrong.
Upvotes: 3
Reputation: 2522
First of all, QThread
is not supposed to be inherited for nearly any reason.
Threading usually will be done like described there: http://qt-project.org/doc/qt-4.8/QThread.html#details
If you just need the thread to count some time and do stuff after a period of time, maybe you can use QTimer
instead and connect the QTimer::timeout()
signal to your slot to display the elapsed time.
Upvotes: 2
Reputation: 63190
I'm sure your loop should look like this:
//initialize timer
int elapsed = this->model->seconds_elapsed;
for (int i = 0; i < elapsed; i++)
I see no need to use a pointer. Keep it simple.
If this still doesn't work, you're doing something else wrong, and it's not obvious from your code.
Also thread signalling isn't done using sleep
. You should look into thread events like semaphore's or condition variables for thread signalling purposes.
If you want to update values periodically, why not use a QTimer?
sleep
has only very few valid uses, and I'm sure that you're solving a problem that doesn't require sleep.
Upvotes: 1