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. [SOLVED] qt threads worker design with blocking while loop
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] qt threads worker design with blocking while loop

Scheduled Pinned Locked Moved General and Desktop
8 Posts 3 Posters 6.8k 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
    alee
    wrote on 13 Sept 2013, 21:57 last edited by
    #1

    i using qt5 and opencv to create an application that give a user inteface using qt and does the image processing part in opencv.....

    so far my design is:

    i am displaying a video and some standard controls like buttons and checkboxes using qt main gui thread

    for capturing image and processing it, i have created a worker class derived from QObject and moved it to a thread....

    the function that is executed in the worker class(Worker::process) has a blocking while loop.....that constantly:

    • captures a frame from a video or a camera
    • does some processing on it
    • converts from cv::Mat to QImage
    • emit a signal to the main thread to display the QImage
    • also in order to recieve user input i was using emitting signal from the main thread to the worker slots

    the problem i faced was that the signal from the main thread never got picked off by the worker because of the event loop blocking while loop.

    after much searching i came up with the solution to use Qt::DirectConnection argument while connecting the signal from the main thread to the worker slots. that solved the problem at that time.

    now i need to add a qtimer or qbasictimer inside the blocking while loop....and guess what, the timer slot(in the case of qtimer) and the protected timerEvent handler (in the case of the qbasictimer) never get called. my hunch is that again the blocking while loop is the culprit

    after much searching and reading on forums i have come to the conclusion that somehow my over all design maybe incorrect.....and as i keep adding more functionality to my application these problems will keep showing up.

    I have two options now:

    somehow call the threads exec() function inside the blocking while loop. so the question to the gurus out there is: "how do i call the thread::exec() method inside a worker QObject class, i need the reference to the thread running the worker to call exec()" (short term solution)

    change the whole implementation.....and here the questions is: "what are my options....." (long term)

    please feel free to ask for details in case my wording or english has made the problem unclear in any way.....thanks...

    1 Reply Last reply
    0
    • ? Offline
      ? Offline
      A Former User
      wrote on 13 Sept 2013, 22:41 last edited by
      #2

      Can you post some code? Without some code we are discussing about "the King's beard" on the other hand, I have a similar problem with OpenGL and threads - your solution could give me some inputs ...

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JKSH
        Moderators
        wrote on 14 Sept 2013, 03:11 last edited by
        #3

        Hi,

        [quote]the function that is executed in the worker class(Worker::process) has a blocking while loop

        ...

        now i need to add a qtimer or qbasictimer inside the blocking while loop….and guess what, the timer slot(in the case of qtimer) and the protected timerEvent handler (in the case of the qbasictimer) never get called. my hunch is that again the blocking while loop is the culprit[/quote]Your analysis is correct. Infinite loops and event loops don't mix -- you must choose one or the other.

        [quote]after much searching i came up with the solution to use Qt::DirectConnection argument while connecting the signal from the main thread to the worker slots. that solved the problem at that time.[/quote]I don't recommend doing this. This makes your slots run in the main thread... not in the thread that the object lives in. QObjects are NOT thread-safe, and should not be accessed from two different threads.

        [quote]I have two options now:

        somehow call the threads exec() function inside the blocking while loop.[/quote]exec() starts running the event loop, which will then block your while loop. An event loop is an infinite loop too :)

        Basically, this approach runs a blocking loop inside a blocking loop, which I'm guessing is not what you want.

        [quote]

        change the whole implementation…..and here the questions is: “what are my options…..” (long term)[/quote]Don't do your processing in an infinite loop. Instead, put the code in a linear function (a slot). Connect this slot to a short timer. Remove Qt::DirectConnection from your code. Your worker thread can now handle your main processing, your timers, and user input.

        Note: If you're running Windows, the timer resolution is limited to about 16ms. If you set the interval to 0, it will run at full speed, but also respond to signals.

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

        1 Reply Last reply
        0
        • A Offline
          A Offline
          alee
          wrote on 14 Sept 2013, 10:13 last edited by
          #4

          bq. willi wrote:
          Can you post some code? Without some code we are discussing about “the King’s beard” on the other hand, I have a similar problem with OpenGL and threads – your solution could give me some inputs …

          @
          class worker : public QObject
          {
          public:
          void process (something);

          slots:
              void input from gui(someparams);
              void stopworker(void);
          

          signals:
          void update_gui(somedatastruct);

          }@

          @ void worker::process(somthing)
          {
          while (condition is true)
          {
          dosomework; //i have included a mutexlocker
          add_delay_here();
          }
          }@

          @void gui::on_pushbutton1_click
          {
          thread = new QThread();
          worker = new Worker;
          worker->moveToThread(thread);
          connect(thread, SIGNAL(started()), worker, SLOT(process()));
          connect(this, SIGNAL(stopworker()), worker, SLOT(stopworker()), Qt::DirectConnection);
          connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
          connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
          connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
          connect(worker, SIGNAL(update_guii(somedatastruct)), this, SLOT(upate_available(somedatastruct)));
          capthread->start();
          }@

          @void gui::on_pushbutton2_click
          {
          emit stopworker();
          }@

          hope this helps in visualising my design......i am new to the forums so forgive any formatting in the code....and any guidance is welcome...be it pertaining to formatting or the actual problem

          1 Reply Last reply
          0
          • A Offline
            A Offline
            alee
            wrote on 14 Sept 2013, 10:38 last edited by
            #5

            bq. JKSH

            Hi, thanks for the very objective and point wise reply. your suggestion have been very helpfull

            a few more questions.....

            1. someone suggested using
              @qApps->processEvents();@

            is this different from the event loop ??

            1. i am also doing some time dependant calculations between frames....
              e,g tracking....and based on that creating a velocity chart.....i need consistant frame rates atleast to milliseconds...as u suggested using timers, the accuracy wont be that good....is there any other way.....can i somehow use some other timers that are more accurate using some other libraries.....obviously they will have to support qt multi thread.....for e,g opencv highgui functions do not work in qt secondary threads.....otherwise i would have used
              @cv::waitKey(milliseconds)@

            regards

            1 Reply Last reply
            0
            • J Offline
              J Offline
              JKSH
              Moderators
              wrote on 16 Sept 2013, 14:57 last edited by
              #6

              You're welcome :)
              [quote author="alee" date="1379155097"]

              1. someone suggested using
                @qApps->processEvents();@

              is this different from the event loop ??
              [/quote]Ah, I forgot about that. Yes, if your loop calls qApp->processEvents() every iteration, then it becomes event loop. But, this method isn't any better than calling exec() to let Qt run its own event loop. In particular, this doesn't solve your timing problem.

              [quote]2. i am also doing some time dependant calculations between frames....
              e,g tracking....and based on that creating a velocity chart.....i need consistant frame rates atleast to milliseconds...as u suggested using timers, the accuracy wont be that good....is there any other way.....can i somehow use some other timers that are more accurate using some other libraries.....obviously they will have to support qt multi thread.....for e,g opencv highgui functions do not work in qt secondary threads.....otherwise i would have used
              @cv::waitKey(milliseconds)@
              [/quote]I just found out that you can use high-precision precise timers by calling QTimer::setTimerType(Qt::PreciseTimer) before you start the timer.

              Ultimately, timer accuracy is influenced by your hardware. What are your PC specs? Also, what operating system are you using?

              But anyway, if the exact time between times between frames is important, you should use a QElapsedTimer to measure the time between frames and calculate your velocity. No matter how precise your timer is, you cannot assume that every iteration has the same interval. This is especially true if:

              • Your operating system is not real-time -- Windows, Mac, and "regular" Linux are not real-time; QNX, vxWorks and Real-Time Linux are real-time.
              • Your thread is also doing other things -- You mentioned that your thread needs to receive user input and run other timers. These activities can affect your frame timer.

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

              1 Reply Last reply
              1
              • A Offline
                A Offline
                alee
                wrote on 16 Sept 2013, 20:09 last edited by
                #7

                thanks JKSH....that was really insightfull...... it will really help me, i was just about to ask u next about some way to calculate elapsed time and you pre-empted my question :D, thanks again.

                I am going to mark this post as solved.

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  JKSH
                  Moderators
                  wrote on 16 Sept 2013, 23:32 last edited by
                  #8

                  You're welcome :) All the best!

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

                  1 Reply Last reply
                  0

                  1/8

                  13 Sept 2013, 21:57

                  • Login

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