задержать выполнение кода с помощью QTimer и Eventloop - PullRequest
0 голосов
/ 28 июня 2018

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

Вот текущее состояние кода, который генерирует поток и соединяет таймер с методом generateData (). Этот код выполняется в конструкторе класса.

timer = new QTimer(0);
timer->setTimerType(Qt::PreciseTimer);
timer->setInterval(40); //25 frames per second


QThread *thread = new QThread(this);
moveToThread(thread);
timer->moveToThread(thread);

connect(thread, SIGNAL(started()), timer, SLOT(start()));
connect(timer, SIGNAL(timeout()), this, SLOT(timerEvent()));
connect(thread, SIGNAL(started()), this, SLOT(generateData()));
connect(this, SIGNAL(finished()), thread, SLOT(quit()));

thread->start();

метод, который должен ждать таймера после выполнения цикла for

void Class::generateData() {
    while (1) {
        calculation()
        //do some calculation, which takes around 3-5ms
        QEventLoop loop;
        connect(timer, SIGNAL(timeout()), &loop, SLOT(quit()));
        loop.exec();
    }
}

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

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Объединяя намеки, которые вы дали на другие ответы, я думаю, это то, что вы ищете:

Class::Class(QObject *parent)
{
    timer = new QTimer(0);
    timer->setTimerType(Qt::PreciseTimer);
    timer->setInterval(40); //25 frames per second

    QThread *thread = new QThread(this);
    moveToThread(thread);
    timer->moveToThread(thread);
    this->moveToThread(thread);

    connect(thread, SIGNAL(started()), timer, SLOT(start()));
    connect(timer, SIGNAL(timeout()), this, SLOT(generateData()));
    connect(this, SIGNAL(finished()), timer, SLOT(stop()));
    connect(this, SIGNAL(finished()), thread, SLOT(quit()));

    thread->start();
}

void Class::generateData()
{
    // Do calculations.
    for (int i = 0; i<object1->size(); ++i)
    {
        object1->at(i)->test();
    }
}

Каждый раз, когда таймер истекает, он запускает функцию generateData в потоке (поскольку вы переместили класс в этот поток). Таймер будет продолжать пульсировать с частотой 25 Гц, поскольку на самом деле это системный вызов (а не активное ожидание в этом потоке). В Windows это может быть недостаточно точным.

Обратите внимание, что вы не можете вызвать moveToThread для этого, если у него есть родители, см. QT docs Также обратите внимание, что Class должен быть производным от QObject, но я думаю, что это уже так, поскольку вы connect ing

0 голосов
/ 28 июня 2018

Ваш подход выглядит ненужно сложным. Я бы сделал следующее:

void Class::generateData()
{
    // Do calculations.
    for (int i = 0; i<object1->size(); ++i)
    {
      object1->at(i)->test();
    }
    // Wait a little bit and do calculations again.
    QTimer::singleShot(40, this, SLOT(generateData()));
}

Обратите внимание, что я избавился от цикла while, потому что таймер рекурсивно вызывает ту же функцию.

...