QT5 Cross-thread communication, slot not called in "this" context

553 views Asked by At

I have an object MainWorker ran as a separate thread thanks to moveToThread method. MainWorker has a member SubWorker which is also ran as a separate thread. Both threads are working in infinite loops.

The idea is, MainWorker and SubWorker both perform some separate computations. Whenever SubWorker is done computing, it should notify MainWorker with the result.

Therefore I intuitively made first connection between signal emitted by SubWorker and a slot of MainWorker, but it wasn't working, so I made two more connections to rule out some potential problems:

connect(subWorker, &SubWorker::stuffDid, this, &MainWorker::reportStuff)); //1
connect(subWorker, &SubWorker::stuffDid, subWorker, &SubWorker::reportStuff); //2
connect(this, &MainWorker::stuffDid, this, &MainWorker::reportStuffSelf); //3

It seems, that what is not working is exactly what I need - cross thread communication, because connection 2 and 3 works as expected. My question is: How do I make connection 1 work?

Edit: Apparently, after Karsten's explanation, it is clear that infinite loop blocks the EventLoop. So the new question is, how can I send messages (signals, whatever) from an infinite loop thread to its parent thread?

I am new to Qt, there is a high chance that I got it completely wrong. Here goes the minimal (not)working example:

MainWorker.h

class MainWorker : public QObject
{
Q_OBJECT

public:
    MainWorker() : run(false) {}

void doStuff()
{
    subWorker = new SubWorker;
    subWorkerThread = new QThread;
    subWorker->moveToThread(subWorkerThread);
    connect(subWorkerThread, &QThread::started, subWorker, &SubWorker::doStuff);
    if(!connect(subWorker, &SubWorker::stuffDid, this, &MainWorker::reportStuff)) qDebug() << "connect failed";
    connect(subWorker, &SubWorker::stuffDid, subWorker, &SubWorker::reportStuff);
    connect(this, &MainWorker::stuffDid, this, &MainWorker::reportStuffSelf);

    subWorkerThread->start();

    run = true;
    while(run)
    {
        QThread::currentThread()->msleep(200);
        emit stuffDid();
    }
}

private:
    bool run;
    QThread* subWorkerThread;
    SubWorker* subWorker;

signals:
    void stuffDid();

public slots:
    void reportStuff()
    {
        qDebug() << "MainWorker: SubWorker did stuff";
    }

    void reportStuffSelf()
    {
        qDebug() << "MainWorker: MainWorker did stuff (EventLoop is not blocked)";
    } 
};

SubWorker.h

class SubWorker : public QObject
{
    Q_OBJECT

public:
    SubWorker() : run(false) {}

    void doStuff()
    {
        run = true;
        while(run)
        {
            qDebug() << "SubWorker: Doing stuff...";
            QThread::currentThread()->msleep(1000);
            emit stuffDid();
        }
    }

private:
    bool run;

public slots:
    void reportStuff()
    {
        qDebug() << "SubWorker: SubWorker did stuff";
    }

signals:
    void stuffDid();
};

main.cpp

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MainWorker *mainWorker = new MainWorker;
    QThread *mainWorkerThread = new QThread;
    mainWorker->moveToThread(mainWorkerThread);
    QObject::connect(mainWorkerThread, &QThread::started, mainWorker, &MainWorker::doStuff);
    mainWorkerThread->start();

    return a.exec();
}
0

There are 0 answers