了解如何在不冻结事件循环的情况下在QThread中休眠/等待

时间:2018-05-05 21:08:55

标签: c++ multithreading qt thread-safety

环顾四周,我发现主要有三个建议在不阻塞事件循环的情况下睡眠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 :(得分:3)

如果你想睡觉QThread使用function getCoordinates($address) { $address = str_replace(" ", "+", $address); // replace all the white space with "+" sign to match with google search pattern $address = str_replace("-", "+", $address); // replace all the "-" with "+" sign to match with google search pattern $url = "http://maps.google.com/maps/api/geocode/json?address=$address"; $response = file_get_contents($url); $json = json_decode($response,TRUE); //generate array object from the response from the web return ($json['results'][0]['geometry']['location']['lat'].",".$json['results'][0]['geometry']['location']['lng']); } 并接受事件被阻止的事实。在大多数情况下,使用QThread::msleep(200);是个坏主意和设计缺陷。

如果要每N秒或毫秒执行一次函数,请使用QCoreApplication::processEvents();并删除任何自写循环。这与QThread :: sleep(N)几乎相同,它不会阻止事件循环,除非QTimer中有昂贵的阻塞代码。