Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem with signal-slot connection across threads [SOLVED]
Forum Updated to NodeBB v4.3 + New Features

Problem with signal-slot connection across threads [SOLVED]

Scheduled Pinned Locked Moved General and Desktop
11 Posts 4 Posters 7.9k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    code_fodder
    wrote on 7 Mar 2014, 20:32 last edited by
    #2

    difficult to say, from the code I can see there is no problem, can you post all the code from worker and subworker (h and c files), I think the issue will become clearer then!

    Alternatively, you could go back a step and forget the thread for now, just create two objects (worker and subworker) connected a signal / slot one in each direction (as you have done) and try that.

    Make sure you declare the signals and the slots in the respective header files.

    Can you send multiple work() signals to the sub worker? - is it getting stuck?

    1 Reply Last reply
    0
    • S Offline
      S Offline
      SGaist
      Lifetime Qt Champion
      wrote on 7 Mar 2014, 20:36 last edited by
      #3

      Hi,

      is subWorkerObj a class member ? If not it will probably be destroyed before it does anything.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • F Offline
        F Offline
        frankiefrank
        wrote on 8 Mar 2014, 16:48 last edited by
        #4

        I'll get some code here asap.

        @SGaist
        subWorkerObj is indeed a class member.

        "Roads? Where we're going, we don't need roads."

        1 Reply Last reply
        0
        • F Offline
          F Offline
          frankiefrank
          wrote on 8 Mar 2014, 17:03 last edited by
          #5

          I might have figured this out. My main application thread is starting my first worker thread but it has it's own loop in a run() method, without calling exec(). Would that mean that for this worker thread there's no event loop to process incoming signals?

          "Roads? Where we're going, we don't need roads."

          1 Reply Last reply
          0
          • S Offline
            S Offline
            SGaist
            Lifetime Qt Champion
            wrote on 8 Mar 2014, 21:31 last edited by
            #6

            I'm not sure I am following you correctly, can you show the related code ?

            Interested in AI ? www.idiap.ch
            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • F Offline
              F Offline
              frankiefrank
              wrote on 9 Mar 2014, 16:08 last edited by
              #7

              I've created a project on the side with the same setup to reproduce the problem.

              It's based off the basic "new Widget Application". In the MainWindow I have a WorkerObjHost running in its own thread, it is creating the WorkerObj running in its own thread, which in turn creates the SubWorker in its own (third thread). The issue is with the connection between Worker and SubWorker.

              Edit: the code here is deemed too complex and lacking event loops to actually process the slots, any late-comers to the thread, please don't spend too much time figuring it out.
              Code:
              MainWindow.h
              @
              // Created this pushButton to start things off
              public slots:
              void on_pushButton_clicked();

              private:
              Ui::MainWindow *ui;
              WorkerObjHost *workerObjHost;
              @

              In MainWindow.cpp
              @
              MainWindow::MainWindow(QWidget *parent) :
              QMainWindow(parent),
              ui(new Ui::MainWindow)
              {
              ui->setupUi(this);
              workerObjHost = new WorkerObjHost(this);
              }

              void MainWindow::on_pushButton_clicked()
              {
              workerObjHost->start();
              }
              @

              WorkerObjHost.h
              @
              #ifndef WORKEROBJHOST_H
              #define WORKEROBJHOST_H

              #include <QThread>
              class WorkerObjHost : public QThread
              {
              public:
              WorkerObjHost(QObject *parent = NULL);
              virtual void run();
              };

              #endif // WORKEROBJHOST_H
              @

              WorkerObjHost.cpp
              @
              #include "workerobjhost.h"
              #include "workerobj.h"

              WorkerObjHost::WorkerObjHost(QObject *parent)
              : QThread(parent)
              {
              }

              void WorkerObjHost::run()
              {
              // not parented here, but seems it doesn't affect outcome
              WorkerObj *worker = new WorkerObj;
              worker->start();

              while (true) {
              // Do some work
              }
              }
              @

              WorkerObj.h
              @
              #ifndef WORKEROBJ_H
              #define WORKEROBJ_H

              #include <QThread>
              #include "subworkerobj.h"

              class WorkerObj : public QThread
              {
              Q_OBJECT

              public:
              WorkerObj(QObject *parent = NULL);

              signals:
              void work();

              public slots:
              void handleSignalFromSubWorker();

              protected:
              virtual void run();
              };

              #endif // WORKEROBJ_H
              @

              WorkerObj.cpp
              @
              #include "workerobj.h"
              #include "subworkerobj.h"

              WorkerObj::WorkerObj(QObject *parent)
              : QThread(parent)
              {
              }

              void WorkerObj::run()
              {
              SubWorkerObj subWorkerObj;
              QThread *subWorkerThread = new QThread;
              subWorkerObj.moveToThread(subWorkerThread);
              subWorkerThread->start();

              // Both connections return true
              bool ok = connect(this, SIGNAL(work()), &subWorkerObj, SLOT(beginWork()));
              ok = connect(&subWorkerObj, SIGNAL(signalFromSubWorker()), this, SLOT(handleSignalFromSubWorker()));

              emit work();

              while (true)
              {
              // do other things
              }
              }

              void WorkerObj::handleSignalFromSubWorker()
              {
              // This doesn't get called
              }
              @

              SubWorkerObj.h
              @
              #ifndef SUBWORKEROBJ_H
              #define SUBWORKEROBJ_H

              #include <QObject>

              class SubWorkerObj : public QObject
              {
              Q_OBJECT

              public:
              SubWorkerObj();

              signals:
              void signalFromSubWorker();

              public slots:
              void beginWork();
              };
              #endif // SUBWORKEROBJ_H
              @

              SubWorkerObj.cpp
              @
              #include "subworkerobj.h"

              SubWorkerObj::SubWorkerObj()
              {
              }

              void SubWorkerObj::beginWork()
              {
              emit signalFromSubWorker();
              }
              @

              "Roads? Where we're going, we don't need roads."

              1 Reply Last reply
              0
              • S Offline
                S Offline
                SGaist
                Lifetime Qt Champion
                wrote on 9 Mar 2014, 20:19 last edited by
                #8

                You're making things overly complicated. You have three levels of thread and none of them has an active event loop. So signals and slots between them will not work as you think.

                Have a look at the latest "QThread documentation":http://qt-project.org/doc/qt-5/qthread.html you'll see there how to implement the worker object paradigm

                Interested in AI ? www.idiap.ch
                Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                1 Reply Last reply
                0
                • F Offline
                  F Offline
                  frankiefrank
                  wrote on 10 Mar 2014, 09:09 last edited by
                  #9

                  Thanks SGaist. You have to guess the rest of the code from what I posted but it's built up that way for a reason (and of course, the original design didn't consider using signals and slots at that point). But I think I can make some changes and get an event loop running.

                  There's something I don't really understand. Is an event loop always necessary on the thread that is supposed to execute the connected slot? It seems that emitting the signal works even if I don't have an event loop, and if the connected slot is on the same thread it executes directly. So basically once I want cross thread signals and slots, I need an event loop on the thread with the slots?

                  "Roads? Where we're going, we don't need roads."

                  1 Reply Last reply
                  0
                  • J Offline
                    J Offline
                    JKSH
                    Moderators
                    wrote on 10 Mar 2014, 11:06 last edited by
                    #10

                    Hi,

                    [quote]Is an event loop always necessary on the thread that is supposed to execute the connected slot?[/quote]Yes.

                    [quote]It seems that emitting the signal works even if I don’t have an event loop,[/quote]You don't need an event loop to emit signals.

                    [quote]and if the connected slot is on the same thread it executes directly.[/quote]Yes, a "DirectConnection":http://qt-project.org/doc/qt-5/qt.html#ConnectionType-enum bypasses the event loop to make a direct function call.

                    [quote] So basically once I want cross thread signals and slots, I need an event loop on the thread with the slots?[/quote]Correct.

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    1 Reply Last reply
                    0
                    • F Offline
                      F Offline
                      frankiefrank
                      wrote on 10 Mar 2014, 11:58 last edited by
                      #11

                      Ah thank you JKSH for clearing some of this out.

                      "Roads? Where we're going, we don't need roads."

                      1 Reply Last reply
                      0

                      11/11

                      10 Mar 2014, 11:58

                      • Login

                      • Login or register to search.
                      11 out of 11
                      • First post
                        11/11
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved