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. Use QCoreApplication::processEvents() in another thread
QtWS25 Last Chance

Use QCoreApplication::processEvents() in another thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 4 Posters 3.9k Views
  • 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.
  • E Offline
    E Offline
    ejm1
    wrote on last edited by
    #1

    Hi, I have a function that blocks my event loop pretty badly, so I used processEvents() to unblock it; however, as the function description warns this function can take some time and if repeatedly called will slow down your program. Which is exactly what happened to me. I have a camera acquiring images, and I would like a QLabel on my App to update with every picture hence the use of processEvents() so my call to update() on the label gets processed. I was wondering if it's possible to run this function in another thread? I'm pretty sure that by opening a new thread I won't be able to access the event loop anymore, right now I have :
    481d1dd5-bb3e-4df0-9cd0-d48ec523e87f-image.png and then a call to fa22ede8-ee96-4670-9dda-c0303a229c1f-image.png . This runs fine; however, it doesn't unblock the event loop. So is there some way to pass those events into this other thread so they can be executed??

    Thanks

    JKSHJ 1 Reply Last reply
    0
    • E ejm1

      Hi, I have a function that blocks my event loop pretty badly, so I used processEvents() to unblock it; however, as the function description warns this function can take some time and if repeatedly called will slow down your program. Which is exactly what happened to me. I have a camera acquiring images, and I would like a QLabel on my App to update with every picture hence the use of processEvents() so my call to update() on the label gets processed. I was wondering if it's possible to run this function in another thread? I'm pretty sure that by opening a new thread I won't be able to access the event loop anymore, right now I have :
      481d1dd5-bb3e-4df0-9cd0-d48ec523e87f-image.png and then a call to fa22ede8-ee96-4670-9dda-c0303a229c1f-image.png . This runs fine; however, it doesn't unblock the event loop. So is there some way to pass those events into this other thread so they can be executed??

      Thanks

      JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by JKSH
      #2

      @ejm1 said in Use QCoreApplication::processEvents() in another thread:

      I was wondering if it's possible to run this function in another thread?

      See https://doc.qt.io/qt-5/qcoreapplication.html#processEvents

      It is possible to run the function in another thread because the function is thread-safe. However, it will only process that thread's events. It won't process your GUI thread's events.

      Also, a thread started by QtConcurrent does not have an event loop so it doesn't have any events.

      So is there some way to pass those events into this other thread so they can be executed??

      No. Events cannot be transferred across threads.

      I have a camera acquiring images, and I would like a QLabel on my App to update with every picture hence the use of processEvents() so my call to update() on the label gets processed.

      What is the frame rate of your camera acquisition?

      Painting an image on QLabel uses CPU rendering which is inefficient. Could you use QCamera + QVideoWidget instead?

      I have a function that blocks my event loop pretty badly

      What does that function do? Can you break it up into smaller functions?

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

      1 Reply Last reply
      2
      • E Offline
        E Offline
        ejm1
        wrote on last edited by
        #3

        @JKSH My frame rate without updating the image is around 63 and with the processEvents it drops to about 40. This function that blocks my event loop is the acquisition loop of the camera. It's a while true loop that doesn't stop acquiring images until a button is pressed on the GUI. Without the processEvents this loop would not know that the button was pressed. I can't really break this up as everything must be in the loop.

        As for your other idea I have never heard of those classes to be honest. I'll have to look into them. They can't be placed with the QtDesigner right? I'd have to code them in the constructor?

        S 1 Reply Last reply
        0
        • E Offline
          E Offline
          ejm1
          wrote on last edited by
          #4

          @JKSH Furthermore I don't think that a Video widget would be appropriate as I only get the images one by one.

          1 Reply Last reply
          0
          • SGaistS Offline
            SGaistS Offline
            SGaist
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Hi,

            Can you explain how the image acquisition is done ?

            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
            • E Offline
              E Offline
              ejm1
              wrote on last edited by
              #6

              @SGaist there is an image buffer that can fit 10 images. If the buffer is full it overwrites one of them depending on the setting I used. Then I pull an image out of the buffer and do some stuff to it such as sending it to my qt application (by reference) and displaying it as a pixmap (this by itself already drops the frames a little but I expected that). Then on my call to processEvents() I lose even more frames because I have to call it for every single frame. But basically I get the images one by one.

              1 Reply Last reply
              0
              • SGaistS Offline
                SGaistS Offline
                SGaist
                Lifetime Qt Champion
                wrote on last edited by
                #7

                What is the format of these images ?

                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
                • E Offline
                  E Offline
                  ejm1
                  wrote on last edited by
                  #8

                  @SGaist

                  Depending on the chosen format (I'm working with polarized light) the image can be grey scale intensity values and in that case its an unsigned char* to a long array of pixel values (Mono8). So there's only one color channel. Basically I just pass this unsigned char* as the "Data" for my QPixMap::fromData().

                  Does this relate to the processEvents calls??

                  1 Reply Last reply
                  0
                  • SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    Trying to determine what is your bottleneck in order to improve your throughput.

                    How are you accessing that camera ?

                    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
                    • E ejm1

                      @JKSH My frame rate without updating the image is around 63 and with the processEvents it drops to about 40. This function that blocks my event loop is the acquisition loop of the camera. It's a while true loop that doesn't stop acquiring images until a button is pressed on the GUI. Without the processEvents this loop would not know that the button was pressed. I can't really break this up as everything must be in the loop.

                      As for your other idea I have never heard of those classes to be honest. I'll have to look into them. They can't be placed with the QtDesigner right? I'd have to code them in the constructor?

                      S Offline
                      S Offline
                      SimonSchroeder
                      wrote on last edited by
                      #10

                      @ejm1 said in Use QCoreApplication::processEvents() in another thread:

                      I can't really break this up as everything must be in the loop.

                      My suggestion is that you try to break up the loop. The easiest replacement is a QTimer with a timeout of 0ms.

                      1. Make the body of your loop a separate slot. (The loop variable needs to become a member variable.)
                      2. Call this slot once by hand to get the first iteration of the loop.
                      3. At the end of the slot create a singleshot QTimer which calls the slot when terminated. Don't forget to increment your loop variable if you have one.

                      A QTimer with a 0ms timeout will fire as soon as possible. It basically places the next iteration of the "loop" into the event queue. Now, you don't have to call processEvents() anymore. This could improve the speed of your video output.

                      Another approach to your problem is to put your loop into an extra thread and thus not block the regular event loop. Be careful with GUI calls. These need to be put into the GUI event loop. You can use QMetaObject::invokeMethod(qApp, ...) for this (the qApp in there is to send it to the context of the GUI thread). I prefer lambdas in this scenario: QMetaObject::invokeMethod(qApp, [this](){ m_label->setText("test"); });

                      1 Reply Last reply
                      0
                      • E Offline
                        E Offline
                        ejm1
                        wrote on last edited by ejm1
                        #11

                        @SimonSchroeder

                        Hi Simon thanks for the response. I'll have to look into the first option, but I do not think the second option will work for me. If the loop is in another thread then any variables that change outside of that thread won't be updated in the loop and I need the loop to be aware that these variables changed (e.g. the user pressed stop to end the loop). I'm not the best programmer, but I don't think there's a way to make a separate thread aware of these changes.

                        As for your first idea, you're basically saying just make my one iteration of my loop an event essentially, so that way everything is always updated afterwards. Why would this speed things up as it's basically equivalent to calling processEvents I think???

                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SimonSchroeder
                          wrote on last edited by SimonSchroeder
                          #12

                          @ejm1 said in Use QCoreApplication::processEvents() in another thread:

                          If the loop is in another thread then any variables that change outside of that thread won't be updated in the loop and I need the loop to be aware that these variables changed (e.g. the user pressed stop to end the loop).

                          All variables are by default shared between threads. So, this approach should work for you as well. You can have, e.g., a boolen variable m_stop_looping which you set to true in the GUI thread and the looping thread will pick it up eventually. 100% proper programming would synchronize access to this variable, e.g. using an atomic variable. However, I would say that you don't need to do this. If you check the variable in every iteration of the loop (and hopefully one iteration does not take too long), you will at most do one extra iteration of the loop. Basically this suggestion is just the inverse of your original post: instead of calling processEvents() in a separate thread (which would handle the GUI stuff if it worked) and doing the work in the current thread, you swap these two threads: Put the work into a separate thread and implicitly have the processEvents() through the regular event loop in the GUI thread.

                          As for your first idea, you're basically saying just make my one iteration of my loop an event essentially, so that way everything is always updated afterwards. Why would this speed things up as it's basically equivalent to calling processEvents I think???

                          I am not entirely sure why this is faster. This is just my experience in general. Maybe there is some overhead involved in call processEvents() compared to just picking the next event from the event loop. I am also not entirely certain if the QTimer event will be pushed to the top of the event loop. I believe Qt does something smart here which helps with what you want.

                          1 Reply Last reply
                          0

                          • Login

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