如何在两个线程中使用movetoThread连接两个QObject之间的信号和插槽

时间:2016-08-08 02:01:52

标签: c++ multithreading qt

我有两个类:A和B,它们都是QObject的子类。

function click(click_id)
{
alert(click_id);
}

我刚才提到this article。 然后在GUI(比如主线程)中,我尝试使用

在不同的线程中在A和B之间交换数据
class A:public QObject
{
Q_OBJECT
public:
A();
~A();
}

sigProduce(double)是A对象中定义的信号,slotConsume(double)是公共插槽: B级标题:

pA = new A();
QThread *workerThread = new QThread;
pA->moveToThread(workerThread);
connect(workerThread , SIGNAL(started()), pA, SLOT(doWork()));
connect(pA, SIGNAL(finished()), workerThread , SLOT(quit()));
connect(pA, SIGNAL(finished()), pA, SLOT(deleteLater()));
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater()));
workerThread ->start();
pB = new B();
connect(pA,SIGNAL(sigProduce(double)),pB,SLOT(slotConsume(double)));//I just don't know where to put this line
QThread *workerThread = new QThread;
pB ->moveToThread(workerThread);
connect(workerThread , SIGNAL(started()), pB , SLOT(doWork()));
connect(pB , SIGNAL(finished()), workerThread , SLOT(quit()));
connect(pB , SIGNAL(finished()), pB , SLOT(deleteLater()));
connect(workerThread , SIGNAL(finished()), workerThread , SLOT(deleteLater()));
workerThread ->start();

所以在程序启动后obj B无法从obj获取双重数据A.连接(pA,pB)代码位置是否重要?有人可以帮助我吗?谢谢。

1 个答案:

答案 0 :(得分:0)

在详细介绍如何解决问题之前,请先确保问题是有效的。如果你使用线程的唯一原因是因为你想要一个无限循环,那么你可能根本不需要线程。如果循环内的工作很轻,那么你可以在主线程中使用QTimer来完成它。请阅读this article以了解有关此内容的更多信息。

无论如何,你遇到的问题是你的doWork方法中有一个无限循环,它会阻塞线程的事件循环。因此,你不得不求助于processEvents。然而,这不是一个好的设计。更好的方法是通过从doWork中删除无限循环让线程返回到事件循环。

然后,您可以使用计时器模拟循环,并在想要停止线程时停止计时器。或者,您可以使用QMetaObject::invokeMethodQt::QueuedConnection来调用事件循环中的doWork方法,并使用bool条件停止工作。在此示例中,我使用了invokeMethod选项:

#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include <QDebug>

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker(QObject *parent = 0) : QObject(parent), _stop(false) {}

public slots:
    void doWork()
    {
        if(_stop)
            return;
        QThread::sleep(1); // simulating some heavy work here
        emit calculationComplete(1564);
        QMetaObject::invokeMethod(this, "doWork", Qt::QueuedConnection);
    }

    void stop()
    {
        _stop = true;
    }

signals:
    void calculationComplete(int result);

private:
    bool _stop;

};

class ResultHandler : public QObject
{
    Q_OBJECT
public:
    ResultHandler(QObject *parent = 0) : QObject(parent) {}

public slots:
    void handleResult(int result)
    {
        // do something with result
        qDebug() << Q_FUNC_INFO << "Result:" << result;
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QThread thread_a;
    Worker worker;
    ResultHandler handler;

    QObject::connect(&worker, &Worker::calculationComplete, &handler, &ResultHandler::handleResult);
    QObject::connect(&thread_a, &QThread::started, &worker, &Worker::doWork);
    QObject::connect(&thread_a, &QThread::finished, &worker, &Worker::stop);

    worker.moveToThread(&thread_a);
    thread_a.start();

    QTimer::singleShot(5000, &thread_a, &QThread::quit); // just simulating an exit

    int result = a.exec();
    thread_a.quit();
    thread_a.wait(5000);
    return result;
}

#include "main.moc"