Pregunta

In my program, I open a window and run a big loop. I display progress in a QTextEdit. I added a cancel button to stop the big loop.

So in the window constructor I run a method that looks like,

void start()
{
    for (size_t i=0, i<10000000; ++i)
    {
        // do some computing
        QApplication::processEvents(); // Else clicking the stop button has no effect until the end of the loop
        if (m_stop) break; // member m_stop set to false at start.
    }
}

So, when I click the stop button, it runs the slot

void stopLoop()
{
    m_stop = true;
}

The problem with that method is that processEvents() slows the execution time a little too much.. But maybe it's inevitable ..

I wanted to try it with signals and slots, but I can't seem to think of how I could connect the pushed stop button with the loop.

Or, signals and slots or not, maybe someone has a better way of achieving this ?

EDIT

Following this thread advice, I now have a worker/thread scenario. So I have in a window constructor

Worker *worker;
QThread *thread ;
worker->moveToThread(thread); 
connect(thread, SIGNAL(started()), worker, SLOT(work()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start(); 

Which seems to work fine. But how could I introduce a QTimer now ?

Should I connect the QTimer to the thread's start() function

connect(timer, &QTimer::timeout, thread, &QThread::start);

Or, should I connect the thread to the QTimer's start() function ?

connect(thread, SIGNAL(started()), timer, &QTimer::start());

Or neither ... but then, how ?

¿Fue útil?

Solución

use a QTimer

void start()
{
    this->timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &MyObject::work);
    connect(stopbutton, &QButton::clicked, timer, &QTimer::stop);
    connect(stopbutton, &QButton::clicked, timer, &QTimer::deleteLater);
    connect(this, &MyObject::stopTimer, timer, &QTimer::deleteLater);
    connect(this, &MyObject::stopTimer, timer, &QTimer::stop);
    timer->setInterval(0);
    timer->setSingleShot(false);
    timer->start();

}

void work()
{
   //do some work and return

   if (done)emit stopTimer();
}

Otros consejos

One thing that you could do to be less "blocky" is to do your work in a worker thread using QThread. Then, the slow-down would not it be such a big problem anymore while you would still be able to gracefully terminate the work.

I would also reconsider this large number iteration in favor of a QTimer. Then, basically the cancel button or the timer's timeout would trigger the worker loop to break. In that case, the while condition for the iteration would be the m_stop guard.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top