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 5.9k 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.
  • 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
              • H hbatalha

                @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 Offline
                JonBJ Offline
                JonB
                wrote on last edited by
                #23

                @hbatalha said in Working with Qthreads:

                when I call it via the void startProcs(const QList<ProcInfo> &toStart) method nothing happens

                What do you expect to happen, which doesn't happen?

                Step through it in a debugger, or put qDebug() statements at judicious places. That's what programming is all about!

                H 1 Reply Last reply
                0
                • H hbatalha

                  @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?

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

                  @hbatalha said in Working with Qthreads:

                  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?

                  I think your knowledge about how Qt works is to "light".
                  Perhaps you should take time to read some parts of Qt documentation:

                  • https://doc.qt.io/qt-5/qtcore-index.html
                  • https://doc.qt.io/qt-5/signalsandslots.html

                  The example class I have written it very lightweight and is just an implementation example to do what you want to do (at least what I have understood):

                  • have a list of process to start
                  • launch next process when first is finished

                  How does it work:
                  the class holds a QProcess member which will start each process and a list which defines the process to be started.
                  In constructor, the signal QProcess::stateChanged is used to be informed when the current process is finished and then start next in queue.

                  Before starting the next process, you could, for example, check the results of previous process, with:

                  • mProc.exitCode() to get application exit code
                  • mProc.readAll() to get application output

                  You could also add signals to Launcher class to be informed about all process done or to give progression, and what ever you need.

                  Again, this is just a code skeleton, to give you a starting point.

                  H 1 Reply Last reply
                  0
                  • JonBJ JonB

                    @hbatalha said in Working with Qthreads:

                    when I call it via the void startProcs(const QList<ProcInfo> &toStart) method nothing happens

                    What do you expect to happen, which doesn't happen?

                    Step through it in a debugger, or put qDebug() statements at judicious places. That's what programming is all about!

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

                    @JonB said in Working with Qthreads:

                    What do you expect to happen, which doesn't happen?

                    I expect tha program.exe will start but it doesn't.

                    Step through it in a debugger, or put qDebug() statements at judicious places. That's what programming is all about!

                    I did , nothing seems to happen when it gets to mProc.start(nextP.procName, nextP.procParameters); . It just finishes up the three elements in the list

                    JonBJ JKSHJ 2 Replies Last reply
                    0
                    • KroMignonK KroMignon

                      @hbatalha said in Working with Qthreads:

                      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?

                      I think your knowledge about how Qt works is to "light".
                      Perhaps you should take time to read some parts of Qt documentation:

                      • https://doc.qt.io/qt-5/qtcore-index.html
                      • https://doc.qt.io/qt-5/signalsandslots.html

                      The example class I have written it very lightweight and is just an implementation example to do what you want to do (at least what I have understood):

                      • have a list of process to start
                      • launch next process when first is finished

                      How does it work:
                      the class holds a QProcess member which will start each process and a list which defines the process to be started.
                      In constructor, the signal QProcess::stateChanged is used to be informed when the current process is finished and then start next in queue.

                      Before starting the next process, you could, for example, check the results of previous process, with:

                      • mProc.exitCode() to get application exit code
                      • mProc.readAll() to get application output

                      You could also add signals to Launcher class to be informed about all process done or to give progression, and what ever you need.

                      Again, this is just a code skeleton, to give you a starting point.

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

                      @KroMignon said in Working with Qthreads:

                      I think your knowledge about how Qt works is to "light".

                      I agree, I will do just that.

                      The example class I have written it very lightweight and is just an implementation example to do what you want to do (at least what I have understood):

                      What I want to achieve is, have a QStringList (selections) with unique arguments id, each argument will be used to start a process in its due time.

                      However, I want theses processes running concurrently but only a given number at one point in time, when one process finishes another one will be started.

                      For example, suppose selections has 5 elements {"1", "2", "3", "4", "5"}, the element 1, 2, 3 will be the first to start the processes and these processes will run at the same time and when e.g. the process with the argument 1 finishes another process, this time with the argument 4, will be started.

                      This code does exactly that, and as pointed out by @JonB it has repeated code and he suggested me trying to understand your example and work with it. That is what I am trying to do but as beginner to GUI programming and QT it is proving to be quite challenging.

                      mProc.exitCode() to get application exit code
                      mProc.readAll() to get application output

                      Tried both, exitcode was 0(zero), and the readAll() shows nothing.

                      Can you provide an example on how you intended the code to be used?

                      KroMignonK 1 Reply Last reply
                      0
                      • H hbatalha

                        @JonB said in Working with Qthreads:

                        What do you expect to happen, which doesn't happen?

                        I expect tha program.exe will start but it doesn't.

                        Step through it in a debugger, or put qDebug() statements at judicious places. That's what programming is all about!

                        I did , nothing seems to happen when it gets to mProc.start(nextP.procName, nextP.procParameters); . It just finishes up the three elements in the list

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

                        @hbatalha said in Working with Qthreads:

                        I expect tha program.exe will start but it doesn't.

                        Your code does not try to execute program.exe, it tries to execute programs.exe or prgram.exe. You don't have any code for checking for errors/output, you wouldn't be informed. Even if it did work, unless you say how you know it has not be run it is not evident you would be sure it had not run. A proper version should use the various other signals of QProcess; and/or put a qDebug() statement into the lambda in your connect() so that you see all QProcess:stateChanged transitions.

                        Glancing now at @KroMignon's code, I'm not sure how it's supposed to work as-is :) The Launcher() constructor does the connect() for the single process mProc, while startNext() re-uses that mProc to launch each process. I'm not sure you're supposed to re-use an existing QProcess instance while it has a process running. But he did say "Something like that, up to you to finish it ;)".

                        His code may work only if you run one process at a time, and wait for one to finish before starting the next. Your start_next_process(), which you say does work, creates a new QProcess for each process, so may be more successful in this case.

                        In principle to get 3 going you should be able to put (at least) 3 into the queue and then call start_next_process() 3 times. Thereafter as one finishes a new one will be pulled and started. I agree you would have to look at how his code works/change it to allow for this. But even with your code earlier, because the body of on_pushButton_3_clicked() is so similar to start_next_process() it looks to me as though on_pushButton_3_clicked() could simply call start_next_process() 3 times rather than repeating code.

                        H 1 Reply Last reply
                        0
                        • H hbatalha

                          @JonB said in Working with Qthreads:

                          What do you expect to happen, which doesn't happen?

                          I expect tha program.exe will start but it doesn't.

                          Step through it in a debugger, or put qDebug() statements at judicious places. That's what programming is all about!

                          I did , nothing seems to happen when it gets to mProc.start(nextP.procName, nextP.procParameters); . It just finishes up the three elements in the list

                          JKSHJ Offline
                          JKSHJ Offline
                          JKSH
                          Moderators
                          wrote on last edited by JKSH
                          #28
                          This post is deleted!
                          1 Reply Last reply
                          0
                          • H hbatalha

                            @KroMignon said in Working with Qthreads:

                            I think your knowledge about how Qt works is to "light".

                            I agree, I will do just that.

                            The example class I have written it very lightweight and is just an implementation example to do what you want to do (at least what I have understood):

                            What I want to achieve is, have a QStringList (selections) with unique arguments id, each argument will be used to start a process in its due time.

                            However, I want theses processes running concurrently but only a given number at one point in time, when one process finishes another one will be started.

                            For example, suppose selections has 5 elements {"1", "2", "3", "4", "5"}, the element 1, 2, 3 will be the first to start the processes and these processes will run at the same time and when e.g. the process with the argument 1 finishes another process, this time with the argument 4, will be started.

                            This code does exactly that, and as pointed out by @JonB it has repeated code and he suggested me trying to understand your example and work with it. That is what I am trying to do but as beginner to GUI programming and QT it is proving to be quite challenging.

                            mProc.exitCode() to get application exit code
                            mProc.readAll() to get application output

                            Tried both, exitcode was 0(zero), and the readAll() shows nothing.

                            Can you provide an example on how you intended the code to be used?

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

                            @hbatalha said in Working with Qthreads:

                            However, I want theses processes running concurrently but only a given number at one point in time, when one process finishes another one will be started.

                            As I wrote before, this was only a basic skeleton, and as @JonB supposed, you can not reuse a QProcess to start another process. That is why it runs only once.

                            So I change the class to create a new QProcess on each process start:

                            class Launcher : public QObject
                            {
                                Q_OBJECT
                            
                               QList<ProcInfo> mProcToStart;
                               QProcess *mProc;
                            public:
                               explicit Launcher(QObject * parent = nullptr) : QObject(parent), mProc(nullptr)
                               {
                               }
                               ~Launcher()
                               {
                                   if(mProc)
                                       mProc->deleteLater();
                               }
                            
                               void startProcs(const QList<ProcInfo> &toStart)
                               {
                                   mProcToStart.append(toStart);
                                   startNext();
                               }
                               bool startNext()
                               {
                                   if(mProcToStart.isEmpty() || (mProc && mProc->state() != QProcess::NotRunning))
                                       return false;
                                   auto nextP = mProcToStart.takeFirst();
                                   mProc = new QProcess();
                                   mProc->setProcessChannelMode(QProcess::MergedChannels);
                                   connect(mProc, &QProcess::stateChanged, [this](QProcess::ProcessState newState) {
                                       if(newState == QProcess::NotRunning)
                                       {
                                           qDebug() << "Process" << mProc->program() << "with arguments" << mProc->arguments()<< "done";
                                           qDebug() << "Exit code is:" << mProc->exitCode();
                                           qDebug() << "Returned data:" << qUtf8Printable(QString::fromLocal8Bit(mProc->readAll()));
                                           qDebug() << "--------------------------------------";
                            
                                           mProc->deleteLater();
                                           mProc = nullptr;
                                           if(!startNext())
                                               emit isDone();
                                       }
                                   });
                                   mProc->start(nextP.procName, nextP.procParameters);
                                   return true;
                               }
                            
                            signals:
                               void isDone();
                            };
                            

                            And here is a working example of use:

                            int main(int argc, char *argv[])
                            {
                                QCoreApplication a(argc, argv);
                            
                                QList<ProcInfo> procs;
                                QStringList defArgs;
                                defArgs
                                        << "-n" << "1"  // Only once
                                        << "-w" << "5000"; // wait up to 5 seconds
                                procs.push_back({"ping.exe", QStringList() << defArgs <<"google.com" });
                                procs.push_back({"ping.exe", QStringList() << defArgs <<"amazon.com" });
                                procs.push_back({"ping.exe", QStringList() << defArgs <<"forum.qt.io" });
                            
                                Launcher l;
                                l.startProcs(procs);
                                QObject::connect(&l, &Launcher::isDone, &a, &QCoreApplication::quit);
                            
                                return a.exec();
                            }
                            

                            But once again, this is only a "playground". Up to you to do adapt this or create a new class to fit your needs.

                            H 1 Reply Last reply
                            1
                            • JonBJ JonB

                              @hbatalha said in Working with Qthreads:

                              I expect tha program.exe will start but it doesn't.

                              Your code does not try to execute program.exe, it tries to execute programs.exe or prgram.exe. You don't have any code for checking for errors/output, you wouldn't be informed. Even if it did work, unless you say how you know it has not be run it is not evident you would be sure it had not run. A proper version should use the various other signals of QProcess; and/or put a qDebug() statement into the lambda in your connect() so that you see all QProcess:stateChanged transitions.

                              Glancing now at @KroMignon's code, I'm not sure how it's supposed to work as-is :) The Launcher() constructor does the connect() for the single process mProc, while startNext() re-uses that mProc to launch each process. I'm not sure you're supposed to re-use an existing QProcess instance while it has a process running. But he did say "Something like that, up to you to finish it ;)".

                              His code may work only if you run one process at a time, and wait for one to finish before starting the next. Your start_next_process(), which you say does work, creates a new QProcess for each process, so may be more successful in this case.

                              In principle to get 3 going you should be able to put (at least) 3 into the queue and then call start_next_process() 3 times. Thereafter as one finishes a new one will be pulled and started. I agree you would have to look at how his code works/change it to allow for this. But even with your code earlier, because the body of on_pushButton_3_clicked() is so similar to start_next_process() it looks to me as though on_pushButton_3_clicked() could simply call start_next_process() 3 times rather than repeating code.

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

                              @JonB said in Working with Qthreads:

                              Your code does not try to execute program.exe

                              It does, I mistyped.

                              you don't have any code for checking for errors/output, you wouldn't be informed.

                              I created the code to check the output, which showed nothing and checked the exitcode too.

                              unless you say how you know it has not be run it is not evident you would be sure it had not run

                              The program when it is finished it will have created files in a specific directory. So I go into that directory to check if it has run.

                              I'm not sure you're supposed to re-use an existing QProcess instance while it has a process running.

                              It has to finish first, right? Maybe that is what is stopping it to work correctly. As I said, I am a complete beginner to Qt, I am still picking up things as I go and you guys are being of great help.

                              it looks to me as though on_pushButton_3_clicked() could simply call start_next_process() 3 times rather than repeating code.

                              I did just that, works perfect, thank you.

                              1 Reply Last reply
                              0
                              • KroMignonK KroMignon

                                @hbatalha said in Working with Qthreads:

                                However, I want theses processes running concurrently but only a given number at one point in time, when one process finishes another one will be started.

                                As I wrote before, this was only a basic skeleton, and as @JonB supposed, you can not reuse a QProcess to start another process. That is why it runs only once.

                                So I change the class to create a new QProcess on each process start:

                                class Launcher : public QObject
                                {
                                    Q_OBJECT
                                
                                   QList<ProcInfo> mProcToStart;
                                   QProcess *mProc;
                                public:
                                   explicit Launcher(QObject * parent = nullptr) : QObject(parent), mProc(nullptr)
                                   {
                                   }
                                   ~Launcher()
                                   {
                                       if(mProc)
                                           mProc->deleteLater();
                                   }
                                
                                   void startProcs(const QList<ProcInfo> &toStart)
                                   {
                                       mProcToStart.append(toStart);
                                       startNext();
                                   }
                                   bool startNext()
                                   {
                                       if(mProcToStart.isEmpty() || (mProc && mProc->state() != QProcess::NotRunning))
                                           return false;
                                       auto nextP = mProcToStart.takeFirst();
                                       mProc = new QProcess();
                                       mProc->setProcessChannelMode(QProcess::MergedChannels);
                                       connect(mProc, &QProcess::stateChanged, [this](QProcess::ProcessState newState) {
                                           if(newState == QProcess::NotRunning)
                                           {
                                               qDebug() << "Process" << mProc->program() << "with arguments" << mProc->arguments()<< "done";
                                               qDebug() << "Exit code is:" << mProc->exitCode();
                                               qDebug() << "Returned data:" << qUtf8Printable(QString::fromLocal8Bit(mProc->readAll()));
                                               qDebug() << "--------------------------------------";
                                
                                               mProc->deleteLater();
                                               mProc = nullptr;
                                               if(!startNext())
                                                   emit isDone();
                                           }
                                       });
                                       mProc->start(nextP.procName, nextP.procParameters);
                                       return true;
                                   }
                                
                                signals:
                                   void isDone();
                                };
                                

                                And here is a working example of use:

                                int main(int argc, char *argv[])
                                {
                                    QCoreApplication a(argc, argv);
                                
                                    QList<ProcInfo> procs;
                                    QStringList defArgs;
                                    defArgs
                                            << "-n" << "1"  // Only once
                                            << "-w" << "5000"; // wait up to 5 seconds
                                    procs.push_back({"ping.exe", QStringList() << defArgs <<"google.com" });
                                    procs.push_back({"ping.exe", QStringList() << defArgs <<"amazon.com" });
                                    procs.push_back({"ping.exe", QStringList() << defArgs <<"forum.qt.io" });
                                
                                    Launcher l;
                                    l.startProcs(procs);
                                    QObject::connect(&l, &Launcher::isDone, &a, &QCoreApplication::quit);
                                
                                    return a.exec();
                                }
                                

                                But once again, this is only a "playground". Up to you to do adapt this or create a new class to fit your needs.

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

                                @KroMignon said in Working with Qthreads:

                                So I change the class to create a new QProcess on each process start:

                                create a new QProcess was one of the many things I tried to see if I could get it to work but now I see I did that wrong.

                                But somehow it is not working with my code, now it is crashing the entire entire application and I can't seem to figure out why. I tried running it as a console application but it is complaining that I isDone is undefined.

                                So, I won't be using your code for now until I gather more knowledge of Qt and also as I have a working code that seems to be ok. But I do want to use it as a console application so I can understand it better and learn from it.

                                As a final request before marking this thread as solved. I would like to know when am I to use this kind of approach or similar.

                                This is my working code now:

                                void Dialog::on_pushButton_3_clicked()
                                {
                                    for(int i = 0; i < 3; ++i)
                                            start_next_process();
                                }
                                
                                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("program.exe", args);
                                    }
                                }
                                

                                What are the differences between your approach and this? ( @JonB I would appreciate hearing this from you also) .

                                Edit: I got the console application working, put the class in its .h file and now it works.

                                JonBJ 1 Reply Last reply
                                0
                                • H hbatalha

                                  @KroMignon said in Working with Qthreads:

                                  So I change the class to create a new QProcess on each process start:

                                  create a new QProcess was one of the many things I tried to see if I could get it to work but now I see I did that wrong.

                                  But somehow it is not working with my code, now it is crashing the entire entire application and I can't seem to figure out why. I tried running it as a console application but it is complaining that I isDone is undefined.

                                  So, I won't be using your code for now until I gather more knowledge of Qt and also as I have a working code that seems to be ok. But I do want to use it as a console application so I can understand it better and learn from it.

                                  As a final request before marking this thread as solved. I would like to know when am I to use this kind of approach or similar.

                                  This is my working code now:

                                  void Dialog::on_pushButton_3_clicked()
                                  {
                                      for(int i = 0; i < 3; ++i)
                                              start_next_process();
                                  }
                                  
                                  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("program.exe", args);
                                      }
                                  }
                                  

                                  What are the differences between your approach and this? ( @JonB I would appreciate hearing this from you also) .

                                  Edit: I got the console application working, put the class in its .h file and now it works.

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

                                  @hbatalha
                                  This looks fine. You should free the QProcess you create via new QProcess. Perhaps your lambda could add process->deleteLater() when NotRunning.

                                  H 1 Reply Last reply
                                  0
                                  • JonBJ JonB

                                    @hbatalha
                                    This looks fine. You should free the QProcess you create via new QProcess. Perhaps your lambda could add process->deleteLater() when NotRunning.

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

                                    @JonB said in Working with Qthreads:

                                    @hbatalha
                                    This looks fine. You should free the QProcess you create via new QProcess. Perhaps your lambda could add process->deleteLater() when NotRunning.

                                    I thought that every object created via new in Qt would be handled somehow by the Qt application itself so the user won't have to worry about memory management (this is what I got from a YouTube video, maybe I got it wrong).

                                    So basically every time, I create a a process via new I will have to add this code?

                                            connect(process, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                            {
                                                if(newState == QProcess::NotRunning)
                                                {
                                                    process->deleteLater();
                                                }
                                            });
                                    

                                    or something like that?

                                    KroMignonK JonBJ 2 Replies Last reply
                                    0
                                    • H hbatalha

                                      @JonB said in Working with Qthreads:

                                      @hbatalha
                                      This looks fine. You should free the QProcess you create via new QProcess. Perhaps your lambda could add process->deleteLater() when NotRunning.

                                      I thought that every object created via new in Qt would be handled somehow by the Qt application itself so the user won't have to worry about memory management (this is what I got from a YouTube video, maybe I got it wrong).

                                      So basically every time, I create a a process via new I will have to add this code?

                                              connect(process, &QProcess::stateChanged, [this](QProcess::ProcessState newState)
                                              {
                                                  if(newState == QProcess::NotRunning)
                                                  {
                                                      process->deleteLater();
                                                  }
                                              });
                                      

                                      or something like that?

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

                                      @hbatalha said in Working with Qthreads:

                                      or something like that?

                                      You are close, you need to capture also process in the lambda:

                                      connect(process, &QProcess::stateChanged, [this, process](QProcess::ProcessState newState)
                                              {
                                                  if(newState == QProcess::NotRunning)
                                                  {
                                                      process->deleteLater();
                                                  }
                                              });
                                      
                                      H 1 Reply Last reply
                                      0
                                      • KroMignonK KroMignon

                                        @hbatalha said in Working with Qthreads:

                                        or something like that?

                                        You are close, you need to capture also process in the lambda:

                                        connect(process, &QProcess::stateChanged, [this, process](QProcess::ProcessState newState)
                                                {
                                                    if(newState == QProcess::NotRunning)
                                                    {
                                                        process->deleteLater();
                                                    }
                                                });
                                        
                                        H Offline
                                        H Offline
                                        hbatalha
                                        wrote on last edited by
                                        #35

                                        @KroMignon
                                        The compiler is complaining about unused this.

                                        dialog.cpp:51:48: warning: lambda capture 'this' is not used
                                        

                                        Is it ok if I remove it when I don't have any this's method call inside the lambda?

                                        A jsulmJ 2 Replies Last reply
                                        0
                                        • H hbatalha

                                          @KroMignon
                                          The compiler is complaining about unused this.

                                          dialog.cpp:51:48: warning: lambda capture 'this' is not used
                                          

                                          Is it ok if I remove it when I don't have any this's method call inside the lambda?

                                          A Offline
                                          A Offline
                                          Anonymous_Banned275
                                          wrote on last edited by
                                          #36

                                          @hbatalha
                                          In theory "warning" is just that and ignoring it "should not" affect the outcome of the code.
                                          Your mileage will vary...

                                          I am still not comfortable with lambda , but if you are looking for whatever ( process, thread etc) to conclude why not say so?

                                          such as
                                          if process done
                                          clean-up whatever

                                          it seems redundant to

                                          if process changed
                                          if process done
                                          cleanup later

                                          Just saying...
                                          Best of luck

                                          PS
                                          I still think you be better off using QConcurrent - definitely less messy...
                                          Your dime...

                                          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