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. Launching a queue of processes (was: "Working with Qthreads")
Forum Updated to NodeBB v4.3 + New Features

Launching a queue of processes (was: "Working with Qthreads")

Scheduled Pinned Locked Moved Solved General and Desktop
41 Posts 8 Posters 7.0k Views 4 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.
  • H Offline
    H Offline
    hbatalha
    wrote on last edited by hbatalha
    #3

    From what I have been reading, I think I need QThreadPool, but I can't seem to find any example that I can understand how it works . This stackoverflow answer is the closest I got so far to be able to understand it.

    I want exactly this behavior:

    600px-Thread_pool.svg.png

    1 Reply Last reply
    0
    • JKSHJ Offline
      JKSHJ Offline
      JKSH
      Moderators
      wrote on last edited by
      #4

      @hbatalha can you provide more details about your tasks?

      For example, if you want to run the same function on every element in a vector, you would use QtConcurrent::map(): https://doc.qt.io/qt-5/qtconcurrentmap.html QtConcurrent takes care of the QThreadPool behind the scenes, so you don't need to manage the pool yourself.

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

      1 Reply Last reply
      1
      • H Offline
        H Offline
        hbatalha
        wrote on last edited by
        #5

        [ @hbatalha can you provide more details about your tasks? ]
        --Every new thread will have a process that it will run.

        I managed to do it (correct me if it is not the best way)

        class Task : public QRunnable
        {
            QString id;
        public:
            Task(QString i) : id(i) {}
        
        protected:
            void run() override
            {
                QString exe = "some_process.exe";
        
                QStringList args;
        
                args << "some_args" << i;
        
                QProcess *process = new QProcess;
        
                process->setProcessChannelMode(QProcess::MergedChannels);
        
                process->start(exe, args);
            }
        };
        
        // I will call it here
        
        void Main::startProcesses()
        {
                QThreadPool *pool = new QThreadPool(this);
             
                 pool->setMaxThreadCount(3);
             
                 for(auto const& e: selections/*QStringList*/)
                 {
                     Task *task = new Task(e)
                     pool->start(task);     
                 }        
        }
        
        

        That is what I got so far.

        KroMignonK JonBJ 2 Replies Last reply
        0
        • H hbatalha

          [ @hbatalha can you provide more details about your tasks? ]
          --Every new thread will have a process that it will run.

          I managed to do it (correct me if it is not the best way)

          class Task : public QRunnable
          {
              QString id;
          public:
              Task(QString i) : id(i) {}
          
          protected:
              void run() override
              {
                  QString exe = "some_process.exe";
          
                  QStringList args;
          
                  args << "some_args" << i;
          
                  QProcess *process = new QProcess;
          
                  process->setProcessChannelMode(QProcess::MergedChannels);
          
                  process->start(exe, args);
              }
          };
          
          // I will call it here
          
          void Main::startProcesses()
          {
                  QThreadPool *pool = new QThreadPool(this);
               
                   pool->setMaxThreadCount(3);
               
                   for(auto const& e: selections/*QStringList*/)
                   {
                       Task *task = new Task(e)
                       pool->start(task);     
                   }        
          }
          
          

          That is what I got so far.

          KroMignonK Offline
          KroMignonK Offline
          KroMignon
          wrote on last edited by
          #6

          @hbatalha said in Working with Qthreads:

          That is what I got so far.

          Why do you use threads to start a process?
          This is not really useful and just add complexity to your application in my eyes.

          H 1 Reply Last reply
          2
          • H hbatalha

            [ @hbatalha can you provide more details about your tasks? ]
            --Every new thread will have a process that it will run.

            I managed to do it (correct me if it is not the best way)

            class Task : public QRunnable
            {
                QString id;
            public:
                Task(QString i) : id(i) {}
            
            protected:
                void run() override
                {
                    QString exe = "some_process.exe";
            
                    QStringList args;
            
                    args << "some_args" << i;
            
                    QProcess *process = new QProcess;
            
                    process->setProcessChannelMode(QProcess::MergedChannels);
            
                    process->start(exe, args);
                }
            };
            
            // I will call it here
            
            void Main::startProcesses()
            {
                    QThreadPool *pool = new QThreadPool(this);
                 
                     pool->setMaxThreadCount(3);
                 
                     for(auto const& e: selections/*QStringList*/)
                     {
                         Task *task = new Task(e)
                         pool->start(task);     
                     }        
            }
            
            

            That is what I got so far.

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by
            #7

            @hbatalha
            One of my bug-bears is that it seems these days that just about every beginner to Qt starts out by trying to use threads. Which are hard to get right, and nearly always turn out to be unnecessary anwyay.

            Please answer @KroMignon's question first, before going any further. If you are wanting to create multiple QProcess to run OS commands, why do you want threads at all?

            1 Reply Last reply
            0
            • KroMignonK KroMignon

              @hbatalha said in Working with Qthreads:

              That is what I got so far.

              Why do you use threads to start a process?
              This is not really useful and just add complexity to your application in my eyes.

              H Offline
              H Offline
              hbatalha
              wrote on last edited by
              #8

              @KroMignon said in Working with Qthreads:

              Why do you use threads to start a process?

              Now that I think about it, it doesn't really seem logical (cause it it isn't?).
              What I want is that I only have 3 processes running at one point in time, the first thing that came to mind was threads, and I can see that this is the wrong way to do it.

              From what I am seeing is that I every time I call pool->start(task) the process will begin and I will end up with all of the processes running at the same time instead of only 3 (please correct me if I am wrong).

              So, how can I achieve what I want, having only 3 processes running at one point in time?

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

                @hbatalha said in Working with Qthreads:

                having only 3 processes running at one point in time?

                Simply start 3 QProcess instances without any threads.

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

                H 1 Reply Last reply
                2
                • H hbatalha

                  @KroMignon said in Working with Qthreads:

                  Why do you use threads to start a process?

                  Now that I think about it, it doesn't really seem logical (cause it it isn't?).
                  What I want is that I only have 3 processes running at one point in time, the first thing that came to mind was threads, and I can see that this is the wrong way to do it.

                  From what I am seeing is that I every time I call pool->start(task) the process will begin and I will end up with all of the processes running at the same time instead of only 3 (please correct me if I am wrong).

                  So, how can I achieve what I want, having only 3 processes running at one point in time?

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by JonB
                  #10

                  @hbatalha
                  As @Christian-Ehrlicher has said. The point is, with Qt when you go QProcess::start(...) this starts the process, but already does not block. The sub-process runs asynchronously, and emits signals when e.g. it has finished (do not use the blocking QProcess::waitForFinished() method). This means that your 3 sub-processes already all run at the same time, without you needing any threads in Qt.

                  1 Reply Last reply
                  0
                  • Christian EhrlicherC Christian Ehrlicher

                    @hbatalha said in Working with Qthreads:

                    having only 3 processes running at one point in time?

                    Simply start 3 QProcess instances without any threads.

                    H Offline
                    H Offline
                    hbatalha
                    wrote on last edited by
                    #11

                    @Christian-Ehrlicher said in Working with Qthreads:

                    Simply start 3 QProcess instances without any threads.

                    How can I make that when one process finishes, another onewill be started?

                    JonBJ 1 Reply Last reply
                    0
                    • H hbatalha

                      @Christian-Ehrlicher said in Working with Qthreads:

                      Simply start 3 QProcess instances without any threads.

                      How can I make that when one process finishes, another onewill be started?

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by JonB
                      #12

                      @hbatalha
                      Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                      H 1 Reply Last reply
                      1
                      • JonBJ JonB

                        @hbatalha
                        Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                        H Offline
                        H Offline
                        hbatalha
                        wrote on last edited by
                        #13

                        @JonB said in Working with Qthreads:

                        @hbatalha
                        Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                        Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                        KroMignonK JKSHJ 2 Replies Last reply
                        0
                        • H hbatalha

                          @JonB said in Working with Qthreads:

                          @hbatalha
                          Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                          Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                          KroMignonK Offline
                          KroMignonK Offline
                          KroMignon
                          wrote on last edited by
                          #14

                          @hbatalha said in Working with Qthreads:

                          Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                          Qt framework is an asynchronous framework, this helps for example for UI to avoid locking the main thread and enable user interactions.

                          One way to do it would be to create a list parameters for the process you want to start and go through this list to start each process at the end of previous one.

                          For example:

                          struct ProcInfo
                          {
                              QString procName;
                              QStringList procParameters;
                              // add what ever you need
                          };
                          

                          Then use this to start each process after the other:

                          class Launcher : public QObject
                          {
                              Q_OBJECT
                          
                             QProcess mProc;
                             QList<ProcInfo> mProcToStart; 
                          public:
                             Launcher(QObject * parent = nullptr) : QObject(parent)
                             {
                                 mProc.setProcessChannelMode(QProcess::MergedChannels);
                                 connect(&mProc, &QProcess:stateChanged, [this](QProcess::ProcessState newState) {
                                     if(newState == QProcess::NotRunning)
                                         startNext();
                                     });
                             }
                          
                             void startProcs(const QList<ProcInfo> &toStart)
                             {
                                 mProcToStart = toStart;
                                 startNext();
                             }
                             void startNext()
                             {
                                  if(mProcToStart .isEmpty())
                                      return;
                                  auto nextP = mProcToStart.takeFirst();
                                  mProc.start(nextP.procName, nextP.procParameters);
                             }
                          };
                          

                          Something like that, up to you to finish it ;)

                          H 1 Reply Last reply
                          2
                          • H hbatalha

                            @JonB said in Working with Qthreads:

                            @hbatalha
                            Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                            Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

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

                            @hbatalha said in Working with Qthreads:

                            @JonB said in Working with Qthreads:

                            Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                            Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                            First, get familiarized with the concept of signals and slots: https://doc.qt.io/qt-5/signalsandslots.html This is a core part of most Qt applications. When you know how to use signals and slots, many things will become clearer.

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

                            H 1 Reply Last reply
                            0
                            • KroMignonK KroMignon

                              @hbatalha said in Working with Qthreads:

                              Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                              Qt framework is an asynchronous framework, this helps for example for UI to avoid locking the main thread and enable user interactions.

                              One way to do it would be to create a list parameters for the process you want to start and go through this list to start each process at the end of previous one.

                              For example:

                              struct ProcInfo
                              {
                                  QString procName;
                                  QStringList procParameters;
                                  // add what ever you need
                              };
                              

                              Then use this to start each process after the other:

                              class Launcher : public QObject
                              {
                                  Q_OBJECT
                              
                                 QProcess mProc;
                                 QList<ProcInfo> mProcToStart; 
                              public:
                                 Launcher(QObject * parent = nullptr) : QObject(parent)
                                 {
                                     mProc.setProcessChannelMode(QProcess::MergedChannels);
                                     connect(&mProc, &QProcess:stateChanged, [this](QProcess::ProcessState newState) {
                                         if(newState == QProcess::NotRunning)
                                             startNext();
                                         });
                                 }
                              
                                 void startProcs(const QList<ProcInfo> &toStart)
                                 {
                                     mProcToStart = toStart;
                                     startNext();
                                 }
                                 void startNext()
                                 {
                                      if(mProcToStart .isEmpty())
                                          return;
                                      auto nextP = mProcToStart.takeFirst();
                                      mProc.start(nextP.procName, nextP.procParameters);
                                 }
                              };
                              

                              Something like that, up to you to finish it ;)

                              H Offline
                              H Offline
                              hbatalha
                              wrote on last edited by hbatalha
                              #16

                              @KroMignon said in Working with Qthreads:

                              Then use this to start each process after the other:

                              Is it possible to run multiple processes at the same time.

                              Also, I couldn't get the code to work, maybe I am missing something or I am using it wrong:

                                  QList<ProcInfo> procs;
                                  Launcher l;
                                  for(auto const& e: selections)
                                  {
                                      QStringList args;
                              
                                      args << "-some_args" << e;
                              
                                      procs.push_back({"program.exe", args});
                                  }
                              
                                  l.startProcs(procs);
                              
                              1 Reply Last reply
                              0
                              • Christian EhrlicherC Offline
                                Christian EhrlicherC Offline
                                Christian Ehrlicher
                                Lifetime Qt Champion
                                wrote on last edited by
                                #17

                                @hbatalha said in Working with Qthreads:

                                Is it possible to run multiple processes at the same time.

                                As I already said - simply create more than one QProcess instance.

                                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
                                0
                                • JKSHJ JKSH

                                  @hbatalha said in Working with Qthreads:

                                  @JonB said in Working with Qthreads:

                                  Like I said, use the signal QProcess::finished. When one sends that, start a new one. That of course makes your processes execute sequentially, instead of at the same time.

                                  Can you provide some example code? I have a basic idea one what you are saying but not enough to translate it to code.

                                  First, get familiarized with the concept of signals and slots: https://doc.qt.io/qt-5/signalsandslots.html This is a core part of most Qt applications. When you know how to use signals and slots, many things will become clearer.

                                  H Offline
                                  H Offline
                                  hbatalha
                                  wrote on last edited by
                                  #18

                                  @JKSH said in Working with Qthreads:

                                  First, get familiarized with the concept of signals and slots: https://doc.qt.io/qt-5/signalsandslots.html This is a core part of most Qt applications. When you know how to use signals and slots, many things will become clearer.

                                  I did it and was able to do this, which works(is it correct?)

                                  void Dialog::on_pushButton_3_clicked()
                                  {
                                      for(int i = 0; i < 3; ++i)
                                      {
                                          QStringList args;
                                  
                                          args << "some_args" << selections.takeFirst();
                                  
                                          QProcess* pro = new QProcess;
                                  
                                          pro->setProcessChannelMode(QProcess::MergedChannels);
                                  
                                          connect(pro, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                          {
                                              if(newState == QProcess::NotRunning)
                                                  start_next_process();
                                          });
                                  
                                          pro->start("program.exe", args);
                                      }
                                  }
                                  
                                  void Dialog::start_next_process()
                                  {
                                      if(!selections.isEmpty())
                                      {
                                          QStringList args;
                                  
                                          args << "some_args" << selections.takeFirst();
                                  
                                          QProcess *process = new QProcess;
                                  
                                          connect(process, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                          {
                                              if(newState == QProcess::NotRunning)
                                                  start_next_process();
                                          });
                                  
                                          process->setProcessChannelMode(QProcess::MergedChannels);
                                  
                                          process->start("prgram.exe", args);
                                      }
                                  }
                                  

                                  I took at look at this but haven't yet completely understood

                                  JonBJ KroMignonK 2 Replies Last reply
                                  0
                                  • H hbatalha

                                    @JKSH said in Working with Qthreads:

                                    First, get familiarized with the concept of signals and slots: https://doc.qt.io/qt-5/signalsandslots.html This is a core part of most Qt applications. When you know how to use signals and slots, many things will become clearer.

                                    I did it and was able to do this, which works(is it correct?)

                                    void Dialog::on_pushButton_3_clicked()
                                    {
                                        for(int i = 0; i < 3; ++i)
                                        {
                                            QStringList args;
                                    
                                            args << "some_args" << selections.takeFirst();
                                    
                                            QProcess* pro = new QProcess;
                                    
                                            pro->setProcessChannelMode(QProcess::MergedChannels);
                                    
                                            connect(pro, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                            {
                                                if(newState == QProcess::NotRunning)
                                                    start_next_process();
                                            });
                                    
                                            pro->start("program.exe", args);
                                        }
                                    }
                                    
                                    void Dialog::start_next_process()
                                    {
                                        if(!selections.isEmpty())
                                        {
                                            QStringList args;
                                    
                                            args << "some_args" << selections.takeFirst();
                                    
                                            QProcess *process = new QProcess;
                                    
                                            connect(process, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                            {
                                                if(newState == QProcess::NotRunning)
                                                    start_next_process();
                                            });
                                    
                                            process->setProcessChannelMode(QProcess::MergedChannels);
                                    
                                            process->start("prgram.exe", args);
                                        }
                                    }
                                    

                                    I took at look at this but haven't yet completely understood

                                    JonBJ Offline
                                    JonBJ Offline
                                    JonB
                                    wrote on last edited by
                                    #19

                                    @hbatalha
                                    You are working from @KroMignon's template. You will not need the QProcess::finished signal I mentioned/your link now refers to because he is effectively doing this (indirectly) via the QProcess::stateChanged signal he connects instead. Which is fine.

                                    Have a look again at his code. In yours you have effectively copied the same block of code out of start_next_process() and into your on_pushButton_3_clicked(). You do not need to do that (repeating the same code is always a suspicious sign). His code is designed for you to use a selections member variable to "queue up" the 3 (in your case) processes you'd like it to run. Your code does no mesh well with that. Please take the time to understand how @KroMignon's approach works.

                                    H 1 Reply Last reply
                                    0
                                    • H hbatalha

                                      @JKSH said in Working with Qthreads:

                                      First, get familiarized with the concept of signals and slots: https://doc.qt.io/qt-5/signalsandslots.html This is a core part of most Qt applications. When you know how to use signals and slots, many things will become clearer.

                                      I did it and was able to do this, which works(is it correct?)

                                      void Dialog::on_pushButton_3_clicked()
                                      {
                                          for(int i = 0; i < 3; ++i)
                                          {
                                              QStringList args;
                                      
                                              args << "some_args" << selections.takeFirst();
                                      
                                              QProcess* pro = new QProcess;
                                      
                                              pro->setProcessChannelMode(QProcess::MergedChannels);
                                      
                                              connect(pro, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                              {
                                                  if(newState == QProcess::NotRunning)
                                                      start_next_process();
                                              });
                                      
                                              pro->start("program.exe", args);
                                          }
                                      }
                                      
                                      void Dialog::start_next_process()
                                      {
                                          if(!selections.isEmpty())
                                          {
                                              QStringList args;
                                      
                                              args << "some_args" << selections.takeFirst();
                                      
                                              QProcess *process = new QProcess;
                                      
                                              connect(process, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                              {
                                                  if(newState == QProcess::NotRunning)
                                                      start_next_process();
                                              });
                                      
                                              process->setProcessChannelMode(QProcess::MergedChannels);
                                      
                                              process->start("prgram.exe", args);
                                          }
                                      }
                                      

                                      I took at look at this but haven't yet completely understood

                                      KroMignonK Offline
                                      KroMignonK Offline
                                      KroMignon
                                      wrote on last edited by
                                      #20
                                      This post is deleted!
                                      1 Reply Last reply
                                      0
                                      • A Offline
                                        A Offline
                                        Anonymous_Banned275
                                        wrote on last edited by
                                        #21

                                        A process is a program that is running on your computer. This can be anything from a small background task, such as a spell-checker or system events handler to a full-blown application like Internet Explorer or Microsoft Word. All processes are composed of one or more threads.

                                        I was under the impression that OP want to
                                        run an individual SINGLE thread in sequence in SINGLE process.

                                        So where do all these "queued multiple instance processes " come from ?
                                        Would it be possible to get back to the original question ?

                                        1 Reply Last reply
                                        0
                                        • JonBJ JonB

                                          @hbatalha
                                          You are working from @KroMignon's template. You will not need the QProcess::finished signal I mentioned/your link now refers to because he is effectively doing this (indirectly) via the QProcess::stateChanged signal he connects instead. Which is fine.

                                          Have a look again at his code. In yours you have effectively copied the same block of code out of start_next_process() and into your on_pushButton_3_clicked(). You do not need to do that (repeating the same code is always a suspicious sign). His code is designed for you to use a selections member variable to "queue up" the 3 (in your case) processes you'd like it to run. Your code does no mesh well with that. Please take the time to understand how @KroMignon's approach works.

                                          H Offline
                                          H Offline
                                          hbatalha
                                          wrote on last edited by hbatalha
                                          #22

                                          @JonB said in Working with Qthreads:

                                          Please take the time to understand how @KroMignon's approach works.

                                          I have read and I partially understand it. What I can't seem to be able to figure out is how does it work well with my code. when I call it via the void startProcs(const QList<ProcInfo> &toStart) method nothing happens, I have tried using it like this:

                                              QList<ProcInfo> mProcToStart;
                                          
                                              for(int i = 0; i < 3; ++i)
                                              {
                                                  QStringList args;
                                          
                                                  args << "some_args" << selections.takeFirst();
                                          
                                                  mProcToStart.push_back({"programs.exe", args});
                                              }
                                          
                                              Launcher launch;
                                          
                                              launch.startProcs(mProcToStart);
                                          

                                          What am missing here?

                                          When it does work, will it run only the three queued processes taken from selections or all of the selections members?

                                          JonBJ KroMignonK 2 Replies 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