Edge case problems
-
I have a project out in user's hands and for the most part it's working well (OS X & Windows) but I'm getting the occasional edge case where the program goes non-responsive (progress bar fills to end and program sits there). If you look at the code below you'll see that I'm using QProcess and a progress bar. Most of the routines in my program are similar, using QProcess to send various commands to an external program (adb, android debug bridge). I can't duplicate these problems and I've tested using Windows XP, Windows 7 and OS X Mav. I thought perhaps resources, so I ran my code under XP with 1Gb of RAM: ran fine w/o issues. Unfortunately, it's all remote, no way I can directly observe.
Any ideas?
@
ui->progressBar->setHidden(false);
ui->progressBar->setValue(0);QTimer *timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(TimerEvent())); timer->start(tsvalue); QProcess install_apk; install_apk.setProcessChannelMode(QProcess::MergedChannels); QString cstring = adb + " install -r " + '"'+ fileName+'"'; install_apk.start(cstring); while(install_apk.state() != QProcess::NotRunning) qApp->processEvents(); command=install_apk.readAll(); ui->progressBar->setHidden(true); if (command.contains("Success")) QMessageBox::information( this, "", "Installed"); else QMessageBox::critical( this, "", "Install failed");
@
-
It's hard to say but a wild guess would be that you're not calling install_apk.waitForStarted(). If the process doesn't "start to start" before you get to the while loop it will be in the NotRunning state, so you'll skip to the readAll() which I don't know what does on the process that didn't start yet.
In any case I would recommend to rewrite this part into a proper OO manner, where you have a worker object that starts the process and reads output in the slot responding to the finished() signal of the process. You wouldn't have to call processEvents() in a loop, which is always a good indicator of refactoring opportunity.
-
Thanks. I'll give this some thought.
-
If I understand correctly, I'm setting up a slot, "RunProcess". I pass it a value (cstring) then when the signal waitForFinished emits it returns the contents of readAll()?
@
QString MainWindow::RunProcess(QString cstring)
{
QProcess run_command;
run_command.setProcessChannelMode(QProcess::MergedChannels);
run_command.start(cstring);
run_command.waitForFinished(-1);
command=run_command.readAll();
return command;
}void MainWindow::on_sideload_Button_clicked()
{QString cstring = adb + " install -r " + '"'+ fileName+'"';
connect(QString command, SIGNAL(waitForFinished()), this, SLOT(RunProcess(cstring)));
}
@The slot RunProcess compiles, but the connect statement fails. Am I on the right track?
-
No, there is no signal waitForFinished. waitForFinished is a blocking method. There is a finished() signal.
@
class Foo : public QObject {
Q_OBJECT
public:
Foo() {
connect(&p, &QProcess::finished, this, &Foo::stuffEnded);
}
void doStuff() {
...
p.start();
}
void stuffEnded(int exitCode, QProcess::ExitStatus exitStatus) {
if(exitCode == 0)
{
p.readAllStandardOutput();
...
}
}
private:
QProcess p;
};
@