alessiop86
alessiop86

Reputation: 1305

Qt thread and loop issue

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

Answers (4)

jonspaceharper
jonspaceharper

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

Sergio Pulgarin
Sergio Pulgarin

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

Zaiborg
Zaiborg

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

Tony The Lion
Tony The Lion

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

Related Questions