Как остановить фоновый цикл после нажатия кнопки?

В моей программе я открываю окно и запускаю большой цикл. Я отображаю прогресс в QTextEdit. Я добавил кнопку отмены, чтобы остановить большой цикл.

Итак, в конструкторе окна я запускаю метод, который выглядит так:

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.
    }
}

Итак, когда я нажимаю кнопку остановки, он запускает слот

void stopLoop()
{
    m_stop = true;
}

Проблема с этим методом заключается в том, что processEvents() слишком сильно замедляет время выполнения.. Но, возможно, это неизбежно..

Я хотел попробовать это с сигналами и слотами, но я не могу придумать, как я мог бы соединить нажатую кнопку остановки с петлей.

Или, сигналы и слоты или нет, может быть, у кого-то есть лучший способ добиться этого?

ИЗМЕНИТЬ

Следуя этому совету, у меня теперь есть сценарий worker/thread. Итак, у меня есть конструктор окна

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(); 

Который, кажется, работает нормально. Но как я мог представить QTimer сейчас?

Должен ли я подключить QTimer к функции start() потока

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

Или мне следует подключить поток к функции start() QTimer?

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

Или ни то ни другое... но тогда как?


person user2287453    schedule 07.04.2014    source источник
comment
Почему бы вам не использовать нить для выполнения тяжелой работы?   -  person OnWhenReady    schedule 07.04.2014


Ответы (2)


использовать 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();
}
person ratchet freak    schedule 07.04.2014
comment
Похоже, это способ сделать это. Но можно ли использовать этот пример с потоком? Смотрите мое редактирование ... Спасибо - person user2287453; 08.04.2014

Одна вещь, которую вы могли бы сделать, чтобы быть менее «блочной», - это выполнять свою работу в рабочем потоке, используя QThread. Тогда замедление больше не будет такой большой проблемой, в то время как вы все равно сможете изящно завершить работу.

Я бы также пересмотрел эту итерацию большого числа в пользу QTimer. Затем, в основном, кнопка отмены или тайм-аут таймера вызовут разрыв рабочего цикла. В этом случае условием while для итерации будет защита m_stop.

person lpapp    schedule 07.04.2014