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. QEventLoop and threads.
Forum Updated to NodeBB v4.3 + New Features

QEventLoop and threads.

Scheduled Pinned Locked Moved Solved General and Desktop
7 Posts 2 Posters 4.5k 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.
  • A Offline
    A Offline
    Alain38 0
    wrote on last edited by
    #1

    Hi,
    I have three classes, a data requester, the application controller, and the application window.

    During its process, in some cases, the data requester detects that one data is missing to be able to continue its process. So it emits a signal to request the missing data. Then it blocks its process (using a QEventLoop) until this data is received.

    The signal is connected (using a queued connection) to a slot in the application controller. If the application controller also does not have this data, it emits a signal to request the data. (otherwise it answers immediately)

    This signal is received by the application window. And the window displays a pop-up (using exec()), si that the user enters the data. Once user has finished, the data is broadcasted to the data requester that stops its event loop and continues its process.

    This process works well when the three classes stand in the main thread. But, there is also cases were the data requester runs in a dedicated thread. In this case, the pop-up is diplayed but it is impossible to enter the data, or to close the window. All user actions are discarded.

    Do you know why? And do you know how I can implement a wiat method that works in the two cases (requested in the main thread or a dedicated thread)?

    Thanks.

    VRoninV 1 Reply Last reply
    0
    • A Alain38 0

      Hi,
      I have three classes, a data requester, the application controller, and the application window.

      During its process, in some cases, the data requester detects that one data is missing to be able to continue its process. So it emits a signal to request the missing data. Then it blocks its process (using a QEventLoop) until this data is received.

      The signal is connected (using a queued connection) to a slot in the application controller. If the application controller also does not have this data, it emits a signal to request the data. (otherwise it answers immediately)

      This signal is received by the application window. And the window displays a pop-up (using exec()), si that the user enters the data. Once user has finished, the data is broadcasted to the data requester that stops its event loop and continues its process.

      This process works well when the three classes stand in the main thread. But, there is also cases were the data requester runs in a dedicated thread. In this case, the pop-up is diplayed but it is impossible to enter the data, or to close the window. All user actions are discarded.

      Do you know why? And do you know how I can implement a wiat method that works in the two cases (requested in the main thread or a dedicated thread)?

      Thanks.

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      @Alain38-0 said in QEventLoop and threads.:

      runs in a dedicated thread

      How are you implementing the new thread?

      In this case, the pop-up is diplayed but it is impossible to enter the data, or to close the window

      This looks like you are starting another event loop in the main thread after the one showing the dialog

      And do you know how I can implement a wiat method that works in the two cases (requested in the main thread or a dedicated thread)?

      What you are doing is already the correct way

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      A 1 Reply Last reply
      0
      • VRoninV VRonin

        @Alain38-0 said in QEventLoop and threads.:

        runs in a dedicated thread

        How are you implementing the new thread?

        In this case, the pop-up is diplayed but it is impossible to enter the data, or to close the window

        This looks like you are starting another event loop in the main thread after the one showing the dialog

        And do you know how I can implement a wiat method that works in the two cases (requested in the main thread or a dedicated thread)?

        What you are doing is already the correct way

        A Offline
        A Offline
        Alain38 0
        wrote on last edited by
        #3

        Hi @VRonin,
        The thread is created through a QtConcurrent. I just did different tries:
        1- Now I'm creating the QEventLoop just in when needed. It was to check if the fact that it was created with the object (so on in the main thread) . But this changes nothing,
        2- Much more surprising. I replaced the QEventLoop by a QMutex. And I still have the same problem.

        I have checked that the pop-up is executed in the main thread. It is the case. I even did a show, followed by a setFocus(), and finally the exec() to be sure that it has the focus.

        More. I put a breakpoint in QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) with the condition d->queuedUserInputEvents.d->begin != d->queuedUserInputEvents.d->end. And this breakpoint never raise, as if my user events were discarded before.

        VRoninV 1 Reply Last reply
        0
        • A Alain38 0

          Hi @VRonin,
          The thread is created through a QtConcurrent. I just did different tries:
          1- Now I'm creating the QEventLoop just in when needed. It was to check if the fact that it was created with the object (so on in the main thread) . But this changes nothing,
          2- Much more surprising. I replaced the QEventLoop by a QMutex. And I still have the same problem.

          I have checked that the pop-up is executed in the main thread. It is the case. I even did a show, followed by a setFocus(), and finally the exec() to be sure that it has the focus.

          More. I put a breakpoint in QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) with the condition d->queuedUserInputEvents.d->begin != d->queuedUserInputEvents.d->end. And this breakpoint never raise, as if my user events were discarded before.

          VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          @Alain38-0 said in QEventLoop and threads.:

          The thread is created through a QtConcurrent.

          Ok, here is the problem. If you create an item in the main thread and then run some methods of if, all the slots triggered by signals will be executed in the main thread (and directly if you don't force Qt::QueuedConnection).

          This is illustrated here: https://doc.qt.io/qt-5.10/threads-technologies.html#choosing-an-appropriate-approach

          Your solution is to implement a worker object in a QThread like described here: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

          The rest should work as it is.

          Your code is mostly correct, you just used the wrong threading technology

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          A 1 Reply Last reply
          2
          • VRoninV VRonin

            @Alain38-0 said in QEventLoop and threads.:

            The thread is created through a QtConcurrent.

            Ok, here is the problem. If you create an item in the main thread and then run some methods of if, all the slots triggered by signals will be executed in the main thread (and directly if you don't force Qt::QueuedConnection).

            This is illustrated here: https://doc.qt.io/qt-5.10/threads-technologies.html#choosing-an-appropriate-approach

            Your solution is to implement a worker object in a QThread like described here: https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

            The rest should work as it is.

            Your code is mostly correct, you just used the wrong threading technology

            A Offline
            A Offline
            Alain38 0
            wrote on last edited by
            #5

            Hi @VRonin,
            I explicitely set Qt::QueuedConnection. Otherwise, in any case, the process should not work when all classes are in the main thread. Because, by default the connection is direct. So the blockingLoop.exec() will be called after the end of the slot, i.e. too late....

            1 Reply Last reply
            0
            • VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by
              #6

              Let me explain better. What I think you have is:

              class DataRequester : public QObject{
              // stuff
              public:
              Q_SIGNAL void iNeedData();
              Q_SLOT void receiveData(const DataPoint& val){
              //stuff
              }
              void calculateData(){
              // stuff
              if(dataIsMissing){
              emit iNeedData();
              QEventLoop eLoop;
              // some connections
              eLoop.exec();
              }
              }
              }
              

              then you have:

              DataRequester dataReq;
              QtConcurrent::run(std::bind(DataRequester::calculateData,&dataReq));
              

              Am I close?
              if so, all the slots will be called in the same thread that called the constructor of the object

              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
              ~Napoleon Bonaparte

              On a crusade to banish setIndexWidget() from the holy land of Qt

              1 Reply Last reply
              2
              • A Offline
                A Offline
                Alain38 0
                wrote on last edited by
                #7

                Hi,
                I have found my problem. In fact I'm using a special class (that I have not implemented) to execute my code through QtConcurrent. I have the source code of this class in front of me... and... it launches a QEventLoop that excludes user events! This is the source of my problem!

                @VRonin, it's you that gave me the solution. By asking me how I'm starting the QThread, I suddenly realized that the problem might come from this class. Thanks.

                1 Reply Last reply
                2

                • Login

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