1

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();
}
styku
  • 146
  • 6
  • 1
    Slots connected to signals from other threads are called through the event loop. As your threads are running infinite loops, the event loop has no chance to run and events are not handled. See [the documentation](http://doc.qt.io/qt-4.8/threads-qobject.html#per-thread-event-loop) about event loops and threads. – Karsten Koop May 04 '16 at 13:19
  • I have came across this remark (and docs) before, however there is one thing I do not understand. From what you say, the EventLoop of MainWorker gets blocked by running SubWorker, right? But then, signals emitted by MainWorker are precessed as expected, so wouldn't that mean the EventLoop is not blocked? – styku May 04 '16 at 13:26
  • Do you mean calling a slot in `MainWorker` from a signal also in `MainWorker` is working as expected? If both signal and slot are in the same thread, the slot function can be called directly, without the event loop. – Karsten Koop May 04 '16 at 13:31
  • I mean that the connection no. 3 (beginning of my question) is working properly. When signal is emitted, slot is called. So connections made between signals and slots within the same thread bypass the EventLoop? What are my chances of starting an infinite loop thread and still being able to communicate with parent thread? – styku May 04 '16 at 13:35
  • 1
    Yes, there are direct connections and queued connections, [see here](http://doc.qt.io/qt-5/threads-qobject.html#signals-and-slots-across-threads). Default uses direct connections within same thread, queued across thread boundary. – Karsten Koop May 04 '16 at 13:38
  • This example runs, but not as expected! A long time without an answer! Are the comments sufficient? Do you need further help? – Roland Jun 24 '16 at 11:02

0 Answers0