Понимание того, как спать / ждать в QThread без замораживания цикла событий - PullRequest
0 голосов
/ 06 мая 2018

Оглядываясь вокруг, я нашел в основном 3 предложения для сна QThread без блокировки цикла событий. Но я не знаю, какой из них наиболее эффективен, или мне следует использовать один или другой в зависимости от обстоятельств.

Может кто-нибудь объяснить мне, что происходит в каждом? Есть ли другое предложение?

ClassB.h

#pragma once

#include <QtCore>
#include <QWaitCondition>
#include <QMutex>
#include <QEventLoop>
#include <QTimer>
#include <QDebug>

class ClassB : public QObject
{
    Q_OBJECT

public:
    ClassB()
    {
        qDebug() << "ClassB::ClassB";

        _timer = new QTimer(this);
        _timer->setInterval(100);
        QObject::connect(_timer, &QTimer::timeout, [this]() { emit continousSignalToClassA(); });
        _timer->start();
    }

    void start()
    {
        qDebug() << "ClassB::start";
        while(true)
        {
            switch (3)
            {
            case 1:
            {
                QThread::msleep(200);
                QCoreApplication::processEvents();
                break;
            }
            case 2:
            {
                QEventLoop loop;
                QTimer::singleShot(200, &loop, SLOT(quit()));
                loop.exec();
                break;
            }
            case 3:
            {
                QWaitCondition w;
                QMutex mutex;
                mutex.lock();
                w.wait(&mutex, 200);
                mutex.unlock();
                QCoreApplication::processEvents();
                break;
            }
            }
            qDebug() << "waiting";
        }
    }

signals:
    void continousSignalToClassA();

private:
    QTimer* _timer;
};

ClassA.h

#pragma once

#include <QThread>
#include <ClassB.h>

class ClassA : public QObject
{
    Q_OBJECT

public:
    ClassA() {}

    void launchClassBThread()
    {
        _classB = new ClassB();

        QObject::connect(this, &ClassA::startClassB, _classB, &ClassB::start);
        QObject::connect(_classB, &ClassB::continousSignalToClassA, this, &ClassA::signalReceived);

        QThread *thread = new QThread();
        _classB->moveToThread(thread);
        thread->start();
        emit startClassB();
    }
    void signalReceived()
    {
        qDebug() << "** I get a signal **";
    }

signals:
    void startClassB();

private:
    ClassB *_classB;
};

main.cpp

#include <QCoreApplication>
#include <ClassA.h>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ClassA classA;
    classA.launchClassBThread();
    return a.exec();
}

1 Ответ

0 голосов
/ 06 мая 2018

Если вы хотите спать QThread, используйте QThread::msleep(200); и принимайте тот факт, что события заблокированы. Использование QCoreApplication::processEvents(); в большинстве случаев является плохой идеей и недостатком дизайна.

Если вы хотите выполнять функцию каждые N секунд или миллисекунд, используйте QTimer::singleShot и удалите все самописанные циклы. Это почти то же самое, что и QThread :: sleep (N), просто оно не блокирует цикл обработки событий, если у вас нет дорогостоящего кода блокировки в QTimer.

...