简体   繁体   中英

qt check QProcess state regularly

I´m starting multiple QProcesses from a textfile (for example different programs like notepad.exe and so on) and want to regularly check if they are still running.

A while loop isn´t the solution, since it is blocking the ui-thread. How can this be achieved? In Java (Android) I would do this with a asynctask connected to a ScheduldExecutorService. Is something similar available for qt?

This is where I start my processes:

void mywidget::startprocesses(QString &text)
{
    QProcess *process = new QProcess(this);
    this->myprocess.append(process);
    process->start(text);
    int state = process->state();
    addlabelstatus(state);
}

And here the method is called:

while(!stream->atEnd())                                    //check stream until empty and assign line as a caption to a new QLabel
        {
            this->fileread = stream->readLine();
            if(!this->fileread.isEmpty())
            {
                central->addlabel(this->fileread);
                central->startprocesses(this->fileread);
            }
        }






void mywidget::addlabelstatus(QProcess::ProcessState newstate)
{
    QString sstring;

    if(newstate == 0)
    {
        QString sstring = "Wird nicht ausgeführt";
        QLabel *label = new QLabel(sstring);
        this->processstatus.append(label);
        this->vrarea->addWidget(label);
    }
    else if (newstate == 1)
    {
        QString sstring = "Wird gestartet!";
        QLabel *label = new QLabel(sstring);
        this->processstatus.append(label);
        this->vrarea->addWidget(label);
    }
    else if (newstate == 2)
    {
        QString sstring = "Wird ausgeführt!";
        QLabel *label = new QLabel(sstring);
        this->processstatus.append(label);
        this->vrarea->addWidget(label);
    }
    else
    {
        QString sstring = "kein Status vorhanden!";
        QLabel *label = new QLabel(sstring);
        this->processstatus.append(label);
        this->vrarea->addWidget(label);
    }
}

Each QProcess has finished(int exitCode, QProcess::ExitStatus exitStatus) and stateChanged(QProcess::ProcessState newState) signals, that emits when some process has been terminated or changed (by type of). So your code can be:

.H side:

public slots:
    void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
    void addlabelstatus(QProcess::ProcessState newState);

.CPP side:

void mywidget::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    <...>
}

void mywidget::addlabelstatus(QProcess::ProcessState newState)
{
    switch(newState) {
        <...>
    };
}

// Your code change

QProcess *process = new QProcess(this);
this->myprocess.append(process);
connect(process, &QProcess::finished, this, &mywidget::processFinished);
connect(process, &QProcess::stateChanged, this, &mywidget::addlabelstatus);
process->start(text);

UPDATE FOR COMMENT QUESTION

You can try this way:

.H side

public slots:
    void processFinished(QLabel *label, int exitCode, QProcess::ExitStatus exitStatus);
    void addlabelstatus(QLabel *label, QProcess::ProcessState newState);

.CPP side

void mywidget::processFinished(QLabel *label, int exitCode, QProcess::ExitStatus exitStatus)
{
    <...>
}

void mywidget::addlabelstatus(QLabel *label, QProcess::ProcessState newState)
{
    switch(newState) {
        <...>
    };
}

while(!stream->atEnd()) {
            this->fileread = stream->readLine();
            if(!this->fileread.isEmpty()) {
                QLabel *label = new QLabel(this->fileread);
                QProcess *process = new QProcess(this);
                this->myprocess.append(process);

                connect(process, &QProcess::finished, [=] 
                (int exitCode, QProcess::ExitStatus exitStatus) 
                { processFinished(label, exitCode, exitStatus); });

                connect(process, &QProcess::stateChanged, [=] 
                (QProcess::ProcessState newState) 
                { addlabelstatus(label, newState); });

                process->start(text);
            }
}

A while loop isn´t the solution, since it is blocking the ui-thread.

Correct. However, since Qt is an event-driven framework, you could use a timer:-

// Assuming we have a list of processes QList<QProcess*> called timerList

QTimer* pTimer = new QTimer;
connect(pTimer, &QTimer::timeout, [=](){

    foreach(QProcess* proc, timerList)
    {
        // get state
        int state = process->state();
        // update UI
        addlabelstatus(state);            
    }

});

pTimer->start(1000); // every second

Or alternatively, as @someoneinthebox answered, connect to each QProcess's stateChanged signal to notify you when it occurs and react to that.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM