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 qtConcurrent function implementation
Forum Updated to NodeBB v4.3 + New Features

Problem with qtConcurrent function implementation

Scheduled Pinned Locked Moved Unsolved General and Desktop
16 Posts 6 Posters 3.5k Views 3 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.
  • KiraK Offline
    KiraK Offline
    Kira
    wrote on last edited by VRonin
    #1

    Hello All,
    Currently i am working on the program where i capture a frame from camera when i receive bit from serial port. The capturing has to be in real-time but the problem was sometimes the program took time to save the image and multiple bit would get accumulated at the serial port. So as solution used QtConcurrent to save the images to harddisk. I am monitoring qconcurrent and if it is not completed saving the image to the queue and processing it later through qconcurrent.

    The logic flow is as follows:

    1. Receive serial data
    2. Check the bit
    3. Check if QTConcurrent is finished && queue is empty
    4. Call qtconcurrent to save the image.
    5. Else if QTConcurrent is running save the image the queue
    6. Have set futurewatcher for qtConcurrent if completed is true it fetches the image from the queue and save the image.

    The problem is that once QTconcurrent is unable to save the image its state, iscompleted state is always false.

    On debugging found the following:

    saveImageFunction(Mat frame, image_name)  //Function called by qconcurrent
    {
        //It enters the function 
        qDebug()<<"Frame Counter"<<frameCounter<<" From "<<QThread::currentThread();
    
        QThread::sleep(2000);  //If i put some delay it returns from this line. dosen't execute any further.
        Due to above line it exists and dosen't execute the below lines and exit. so the state is always false.
        //Logic to save the image and give confirmation of the image save. 
    }
    

    Note: When i run the program normally it execute the lines but at some point it fails and state always remain false.

    When i write simple commands like print and cout etc it works fine but it creates problem for image save function or when some delay is introduced.

    Could not determine exactly where the issue is plase let me know in case of any other details.

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

      That behavior sounds odd, but it's hard to say without more code to understand how things interact. I think it would help a lot if you could post the QtConcurrent call, the logic that decides whether to start QtConcurrent or put things in the queue, and maybe a bit more of your saveImage function.

      1 Reply Last reply
      1
      • mranger90M Offline
        mranger90M Offline
        mranger90
        wrote on last edited by
        #3

        Without more code I couldn't tell you why the QtConcurrent call to saveImageFunction is hanging. But, I also believe this is a design issue.
        I've done a lot of work with saving video image data, and usually I keep a separate thread going all the time to monitor the image queue. When the image comes in from the source, it is inserted or copied into the queue, (usually by a signal) and the thread that is monitoring it will do the save to disk or other processing. This way you are not spawning a thread when every image comes in.

        KiraK 1 Reply Last reply
        0
        • mranger90M mranger90

          Without more code I couldn't tell you why the QtConcurrent call to saveImageFunction is hanging. But, I also believe this is a design issue.
          I've done a lot of work with saving video image data, and usually I keep a separate thread going all the time to monitor the image queue. When the image comes in from the source, it is inserted or copied into the queue, (usually by a signal) and the thread that is monitoring it will do the save to disk or other processing. This way you are not spawning a thread when every image comes in.

          KiraK Offline
          KiraK Offline
          Kira
          wrote on last edited by
          #4

          @mranger90 , @Asperamanca @J-Hilk:
          Hello eveyone sharing the logic code of implementation please have a look:

          Sharing the Logic of Saving Image using QtConcurrent:

          MainWindow.h

          struct SaveImage{
          // char fileName[100];
          String filename;
          Mat image; // Please note mat is a class of opencv

          SaveImage(){}
          
          SaveImage(String file , Mat img){
              file = filename;
              image = img;
          }
          

          };

          class MainWindow : public QMainWindow
          {


          Declarations

          QQueue<SaveImage> saveQueue;
          QFuture<void> future;
          QFutureWatcher<void> watcher;
          


          };

          MainWindow.cpp

          MainWindow constructor:
          watcher.setFuture(future);
          connect(&watcher, &QFutureWatcher<void>::finished, this,&MainWindow::processQueue);

          Mainwindow readData() // It is slot which gets called data arrives at serialport

          if serial data contains given value call
          newSaveRequestFromSerialPort() // It is main function which is descibed below

          MainWindow::newSaveRequestFromSerialPort()

          //The function perform the following
          Request the frame from the camera and store it

          if(future.isFinished() && saveQueue.isEmpty()) {
          future = QtConcurrent::run(this,&MainWindow::saveConcurrentImage,saveImage,capturedFrame);
          }else{
          elapsedQueue.start();
          saveQueue.append(SaveImage(saveImage,capturedFrame));
          qDebug()<<"Size of the queue"<< saveQueue.size();
          int millisecqueue = elapsedQueue.elapsed();
          qDebug()<<"Time taken to save to queue"<<millisecqueue;
          }

          MainWindow::processQueue //This function is called above when qwatcher is finished:

          if(!saveQueue.isEmpty()){
          //Save queue is not Empty
          if(future.isFinished()){
          //Double check to be sure
          SaveImage str = saveQueue.takeFirst(); //Removes first element;
          future = QtConcurrent::run(this,&MainWindow::saveConcurrentImage,str.filename,str.image);
          }

          MainWindow::saveConcurrentImage(String fileName, Mat capturedFrame)
          It is function called in qconcurrent
          It takes received image and store it drive.

          My problem is if i create a delay in the saveConcurrentImage such as QThread::sleep(2000);
          Future never gets completed and image starts getting saved in the queue.
          But if i remove the wait in the above function everything works fine.

          J.HilkJ 1 Reply Last reply
          0
          • A Offline
            A Offline
            Asperamanca
            wrote on last edited by Asperamanca
            #5

            Are you sure you want to sleep for 2000 seconds? That's what your code says...

            EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

            J.HilkJ 1 Reply Last reply
            0
            • KiraK Kira

              @mranger90 , @Asperamanca @J-Hilk:
              Hello eveyone sharing the logic code of implementation please have a look:

              Sharing the Logic of Saving Image using QtConcurrent:

              MainWindow.h

              struct SaveImage{
              // char fileName[100];
              String filename;
              Mat image; // Please note mat is a class of opencv

              SaveImage(){}
              
              SaveImage(String file , Mat img){
                  file = filename;
                  image = img;
              }
              

              };

              class MainWindow : public QMainWindow
              {


              Declarations

              QQueue<SaveImage> saveQueue;
              QFuture<void> future;
              QFutureWatcher<void> watcher;
              


              };

              MainWindow.cpp

              MainWindow constructor:
              watcher.setFuture(future);
              connect(&watcher, &QFutureWatcher<void>::finished, this,&MainWindow::processQueue);

              Mainwindow readData() // It is slot which gets called data arrives at serialport

              if serial data contains given value call
              newSaveRequestFromSerialPort() // It is main function which is descibed below

              MainWindow::newSaveRequestFromSerialPort()

              //The function perform the following
              Request the frame from the camera and store it

              if(future.isFinished() && saveQueue.isEmpty()) {
              future = QtConcurrent::run(this,&MainWindow::saveConcurrentImage,saveImage,capturedFrame);
              }else{
              elapsedQueue.start();
              saveQueue.append(SaveImage(saveImage,capturedFrame));
              qDebug()<<"Size of the queue"<< saveQueue.size();
              int millisecqueue = elapsedQueue.elapsed();
              qDebug()<<"Time taken to save to queue"<<millisecqueue;
              }

              MainWindow::processQueue //This function is called above when qwatcher is finished:

              if(!saveQueue.isEmpty()){
              //Save queue is not Empty
              if(future.isFinished()){
              //Double check to be sure
              SaveImage str = saveQueue.takeFirst(); //Removes first element;
              future = QtConcurrent::run(this,&MainWindow::saveConcurrentImage,str.filename,str.image);
              }

              MainWindow::saveConcurrentImage(String fileName, Mat capturedFrame)
              It is function called in qconcurrent
              It takes received image and store it drive.

              My problem is if i create a delay in the saveConcurrentImage such as QThread::sleep(2000);
              Future never gets completed and image starts getting saved in the queue.
              But if i remove the wait in the above function everything works fine.

              J.HilkJ Offline
              J.HilkJ Offline
              J.Hilk
              Moderators
              wrote on last edited by
              #6

              @Kira
              hi,

              I don't quite get why you want to sleep the thread in the first place?

              By calling QThread::spleep, all event managment is halted and Signal/Slot stuff is actually, I believe, dropped/ignored. This might be the reason why QFuture does not return correctly.

              That said, the idea behind Qt::Concurrent is a fire and forget type of 2nd thread.
              You passing QtConcurrent data and tell it to write it, and want to know when its done.
              Now you tell it, take this data, write it and wait 2 seconds before you tell me you're done.

              Techincally, you don't need QFuture in the first place, if you're certain that you won't start more than a handful of Save-functions simultaniously.
              In that case,just drop it. You can have multiple QtConcurrents running concurrently. I don't think there's an actual limit, but if you exceed your OS-optimal thread count, the overall process will slow down.


              Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


              Q: What's that?
              A: It's blue light.
              Q: What does it do?
              A: It turns blue.

              1 Reply Last reply
              2
              • A Asperamanca

                Are you sure you want to sleep for 2000 seconds? That's what your code says...

                EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

                J.HilkJ Offline
                J.HilkJ Offline
                J.Hilk
                Moderators
                wrote on last edited by
                #7

                @Asperamanca said in Problem with qtConcurrent function implementation:

                Are you sure you want to sleep for 2000 seconds? That's what your code says...

                EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

                good catch,

                but thats not a bug, Qthread has 3 Sleep functions:

                void	msleep(unsigned long msecs) //Miliseconds
                void	sleep(unsigned long secs)        //Seconds
                void	usleep(unsigned long usecs)   //Microseconds
                

                Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                Q: What's that?
                A: It's blue light.
                Q: What does it do?
                A: It turns blue.

                A KiraK 2 Replies Last reply
                2
                • J.HilkJ J.Hilk

                  @Asperamanca said in Problem with qtConcurrent function implementation:

                  Are you sure you want to sleep for 2000 seconds? That's what your code says...

                  EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

                  good catch,

                  but thats not a bug, Qthread has 3 Sleep functions:

                  void	msleep(unsigned long msecs) //Miliseconds
                  void	sleep(unsigned long secs)        //Seconds
                  void	usleep(unsigned long usecs)   //Microseconds
                  
                  A Offline
                  A Offline
                  Asperamanca
                  wrote on last edited by
                  #8

                  @J.Hilk said in Problem with qtConcurrent function implementation:

                  @Asperamanca said in Problem with qtConcurrent function implementation:

                  Are you sure you want to sleep for 2000 seconds? That's what your code says...

                  EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

                  good catch,

                  but thats not a bug, Qthread has 3 Sleep functions:

                  void	msleep(unsigned long msecs) //Miliseconds
                  void	sleep(unsigned long secs)        //Seconds
                  void	usleep(unsigned long usecs)   //Microseconds
                  

                  I know. It's still easy to make a mistake. Type-rich programming can really help here.

                  1 Reply Last reply
                  1
                  • J.HilkJ J.Hilk

                    @Asperamanca said in Problem with qtConcurrent function implementation:

                    Are you sure you want to sleep for 2000 seconds? That's what your code says...

                    EDIT: Based on this experience, I posted the following suggestion: https://bugreports.qt.io/browse/QTBUG-67367

                    good catch,

                    but thats not a bug, Qthread has 3 Sleep functions:

                    void	msleep(unsigned long msecs) //Miliseconds
                    void	sleep(unsigned long secs)        //Seconds
                    void	usleep(unsigned long usecs)   //Microseconds
                    
                    KiraK Offline
                    KiraK Offline
                    Kira
                    wrote on last edited by
                    #9

                    @J.Hilk @Asperamanca : Thanks both of you for your reply.
                    Actually i am not using sleep in my program it was to test a scenario.

                    The qconcurrent works properly initially but sometimes the save function takes more time to save and QtConcurrent is busy executing the task. By the time the request arises at the serial port so QFuture returns false and image is saved to the queue.

                    So the problem arises here. After this event occurs QFuture iscompleted never returns true and image keeps on getting saved to the queue.

                    On debugging line by line i found that when entering the QTConcurrent loops to analyse the flow i introduce a time delay by the time value gets generated at serial port setting the future completed to false.
                    But after that qfuture never returns true.

                    The purpose of entering sleep was to figure out whether a wait time in the qtconcurrent function caused the below problem.

                    1 Reply Last reply
                    0
                    • KiraK Offline
                      KiraK Offline
                      Kira
                      wrote on last edited by
                      #10

                      @J-Hilk : Would it a better idea if i append the image in queue and run qtconcurrent to save the image or should i go with the QThread approach

                      J.HilkJ 1 Reply Last reply
                      0
                      • Christian EhrlicherC Offline
                        Christian EhrlicherC Offline
                        Christian Ehrlicher
                        Lifetime Qt Champion
                        wrote on last edited by
                        #11

                        I don't understand why you need to use the same QFuture every time. Why not just create a new future every time and use a QThreadPool to avoid thread creation overhead as explained e.g. here: http://doc.qt.io/qt-5/qtconcurrentrun.html

                        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                        Visit the Qt Academy at https://academy.qt.io/catalog

                        KiraK 1 Reply Last reply
                        1
                        • Christian EhrlicherC Christian Ehrlicher

                          I don't understand why you need to use the same QFuture every time. Why not just create a new future every time and use a QThreadPool to avoid thread creation overhead as explained e.g. here: http://doc.qt.io/qt-5/qtconcurrentrun.html

                          KiraK Offline
                          KiraK Offline
                          Kira
                          wrote on last edited by
                          #12

                          @Christian-Ehrlicher : I want to keep the order of saving the image sequential.
                          Also if suppose i create new QFuture everytime and the thread pool executes a qtconcurrent function which never returns true as happening in my situation it would lead to arise a situation like deadlock.

                          kshegunovK 1 Reply Last reply
                          0
                          • KiraK Kira

                            @J-Hilk : Would it a better idea if i append the image in queue and run qtconcurrent to save the image or should i go with the QThread approach

                            J.HilkJ Offline
                            J.HilkJ Offline
                            J.Hilk
                            Moderators
                            wrote on last edited by
                            #13

                            @Kira QThread is an option,

                            but from what you describe, the case that a 2nd Save request arrives while the old one is still ongoing is rather rare, I would simply go without QFuture and QFuturWatcher and simply call QtConcurrent. The liklyhood that the 2nd save function finished before the first is very very very slim.


                            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                            Q: What's that?
                            A: It's blue light.
                            Q: What does it do?
                            A: It turns blue.

                            KiraK 1 Reply Last reply
                            0
                            • J.HilkJ J.Hilk

                              @Kira QThread is an option,

                              but from what you describe, the case that a 2nd Save request arrives while the old one is still ongoing is rather rare, I would simply go without QFuture and QFuturWatcher and simply call QtConcurrent. The liklyhood that the 2nd save function finished before the first is very very very slim.

                              KiraK Offline
                              KiraK Offline
                              Kira
                              wrote on last edited by
                              #14

                              @J.Hilk : As per the program logic it can be possible because there is possibility that the qfuture is working and other save request arises because data at serial port is responsible for generating the request. Serial port read function is independent of the qfuture event.
                              Please correct me if i am wrong!
                              So if i remove qfuture would QtConcurrent would generate two threads ? And if its so possible then would the second thread can be completed before the first thread.

                              1 Reply Last reply
                              0
                              • Christian EhrlicherC Offline
                                Christian EhrlicherC Offline
                                Christian Ehrlicher
                                Lifetime Qt Champion
                                wrote on last edited by
                                #15

                                QtConcurrent::run() will never block ... please take a look at the documentation: http://doc.qt.io/qt-5/qtconcurrent.html#run

                                Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                                Visit the Qt Academy at https://academy.qt.io/catalog

                                1 Reply Last reply
                                1
                                • KiraK Kira

                                  @Christian-Ehrlicher : I want to keep the order of saving the image sequential.
                                  Also if suppose i create new QFuture everytime and the thread pool executes a qtconcurrent function which never returns true as happening in my situation it would lead to arise a situation like deadlock.

                                  kshegunovK Offline
                                  kshegunovK Offline
                                  kshegunov
                                  Moderators
                                  wrote on last edited by kshegunov
                                  #16

                                  @Kira said in Problem with qtConcurrent function implementation:

                                  I want to keep the order of saving the image sequential.

                                  Use a QThread with a worker object to save the images (sequentially), and don't block the event loop ever - read the serial port as fast as possible and then delegate the IO operation to the io thread through a signal. Something like this (needs to go in the appropriate class and the thread and object should be members, code untested):

                                  QThread ioThread;
                                  ioThread.start();
                                  
                                  QObject ioWorker;
                                  ioWorker.moveToThread(&ioThread);
                                  
                                  QObject::connect(this, &MainWindow::saveConcurrentImage, &ioWorker, [] (String fileName, Mat capturedFrame) -> void  {
                                       // ... Saving to disk goes here
                                  });
                                  

                                  You will also need to have Q_DECLARE_METATYPE for your String and Mat, and qRegisterMetatype at the beginning of your main to leverage argument packing for queued connections.

                                  PS.
                                  If you use stack objects, you need this piece in the class' destructor to ensure proper cleanup:

                                  MainWindow::~MainWindow()
                                  {
                                      ioThread.quit();
                                      ioThread.wait();
                                  }

                                  Read and abide by the Qt Code of Conduct

                                  1 Reply Last reply
                                  3

                                  • Login

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