Running multiple QProcess



  • I have following function which stores images in a folder and at the end starts a QProcess which will create a video out of it.

    void Recorder::recordThread(){
    	//...
    	while(recording){
    		//save images
    	}
    	
    	process.start("C:\\ffmpeg.exe", QStringList() <<"-i"<< picDir.c_str() << "-r"<< "30" << "-vcodec"<< "ffv1" << filename.c_str());		
    }
    

    This function is executed as a thread like this:

    void Recorder::setup(){
    	if (!recordingThread){
    		recording=true;      
    		recordingThread.reset(new std::thread(&Recorder::recordThread, this));
    	}
    }
    

    recordingThread is a std::unique_ptrstd::thread

    Now the problem is that while there can only be one recordingThread running at any point, the QProcess will take some time to finish and it can happen that recordThread() wants to start the next process while the first one hasn't finished yet.

    How can I allow to have multiple QProcess running?

    Starting the process as startDetached() worked as intended but it does open up the command line window temporarily which isn't ideal for the user.

    One problem I am having with this is that only the started() signal is being emited. finished() isn't. I connect the signals/slots in the constructor.

    To summarize my problem: I wan't to be able to safely start a new QProcess in the recordThread() function while there is still another one running from the previous time the function was called.


  • Moderators

    Hi,
    so your problem is that a QProcess can only run one process at a time, right? Then why don't use multiple instances of QProcess?


  • Moderators

    @testus
    Instead of having only one instance of "QProcess process;" propbably declared in your class definition, you may use a list or a vector of pointers to QProcess. You can start those processes and connect the signals as required.
    If you connect all to the same finished slot method, you can use state() to find the process finished. The ones finished you can remove from the list.

    This is possible to do. You need to careful for not starting too many processes, which may stall your machine.



  • I did think about creating a vector of QProcess for this but I would have know when the process has finished so I can delete it. Like I said the finished() signal never get emitted for some reason. started() works.
    I also tried to create a pointer to QProcess but then I don't get any signals not even started(). Is that normal?


  • Moderators

    I think the problem is that you don't have an event queue in your recordThread that processes any signals. The started() signal might get posted to your GUI thread's event queue before the thread affinity of the QProcess instance changes (but I can't tell for sure from the few lines of code).



  • The only code I removed from the posted recordThread() function was related to getting the directory names and writting the files.

    Here is how I stop the thread:

    void Recorder::stopRecording(){
    	recording = false;
    	if (recordingThread) {
    		recordingThread->join();
    		recordingThread.reset();      
    	}
    }
    

    So the recordThread() event finishes after starting the QProcess. QProcess process is declared in the header and I connect the slots in the constructor. Like I said, I first tried to create pointers to QProcess in the recordThread() but that didn't emit any signals either. Not even started().

    edit:
    This is how I tried to use the pointer in the recordThread(); I'm not even thinking about multiple QProcess in this example. I'm just trying to get the signals to work.

    proc = new QProcess();
    proc->start("C:\\ffmpeg.exe", QStringList() <<"-i"<< picDir.c_str() << "-r"<< "30" << "-vcodec"<< "ffv1" << filename.c_str());
    connect(proc,SIGNAL(started()),this,SLOT(startedFFMPEG()));
    proc->waitForStarted();
    

    The process runs correctly but the signal is never emitted.


  • Moderators

    @testus
    It could well that
    @Wieland said:

    I think the problem is that you don't have an event queue in your recordThread that processes any signals. The started() signal might get posted to your GUI thread's event queue before the thread affinity of the QProcess instance changes (but I can't tell for sure from the few lines of code).

    this is part of your problem.

    You so not show that you are keeping the pointers somehwere. Otherwise it does most of the time actually work, but you are creating memory leaks. Also this might be a reason that you are not receiving a finished signal.

    I am using such a mechanism in a small tool which has to start quite a number of processes in a row. It have a separate slotmethod created which is triggered through a QTimer. The slot method is checking the stack of processes running and eliminate those which have finished state. Not really elegant, it works.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.