简体   繁体   中英

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?

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.

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 .

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM