Der richtige Gebrauch von QProcess
- Plattform: Qt 4.8.2, Win 7
Bitte beachten Sie die folgende Logik flow:
1. App started
2. functionA() triggered
3. the app periodically capture some images to external files
4. end of functionA()
5. the app create a video from captured images, using ffmpeg as external program
6. [step 2 -> step 5] may be repeated.
7. App quit
Erreichen den Fluss, ich benutze QProcess starten externes Programm für mich in die Bilder, aber ich war verwirrt mit der richtigen Nutzung Muster von QProcess. (I don ' T care über die Konsole-Meldungen von ffmpeg, die ich bestimmen den Erfolg von Schritt 5 mit der überprüfung, ob die video-Datei erstellt).
Versuch 1
void MyWidget::createAVI()
{
checkAndDeleteAVI();
process = new QProcess(this); //process_ defined as class member;
process->start("ffmpeg -f images2 ....");
process->waitForFinished(-1); //(a)
//(b)
}
Unter (a), ich Lesen Sie die Dokumentation, die diesem Aufruf kann das einfrieren der GUI, also sollte ich Anruf von QThread/QRunnable?
Unter (b), bin ich vermisste von etwas hier? wie, wenn ich versuche, die app schließen (Schritt 7 in der Strömung), die app stürzt ab, und ich dachte, dass die erzeugte QProcess ist nicht ordnungsgemäß freigegeben wird.
Versuch 2
Schrieb ich eine wrapper-Klasse QProcess wie folgt:
Launcher.h
class Launcher : public QObject
{
Q_OBJECT
public:
/** constructor */
explicit Launcher(QObject *parent = 0);
/** destructor */
~Launcher() {
if (started_ && process_->state() != QProcess::NotRunning)
process_->kill();
} //end_dtor(Launcher)
Q_SIGNALS:
void feedbackLog(QString log);
public Q_SLOTS:
void launch(QString program, QStringList argList);
private:
QProcess * process_;
bool started_;
private Q_SLOTS:
void error(QProcess::ProcessError error);
void finished(int exitCode, QProcess::ExitStatus status);
void stateChanged(QProcess::ProcessState state);
}; //end_class(Launcher)
#endif //LAUNCHER_H
Launcher.cpp
#include "launcher.h"
#include <QCoreApplication>
#include <QtDebug>
Launcher::Launcher(QObject *parent) : QObject(parent), started_(false)
{
process_ = new QProcess(this);
connect(process_,
SIGNAL(error(QProcess::ProcessError)),
SLOT(error(QProcess::ProcessError)));
connect(process_,
SIGNAL(finished(int, QProcess::ExitStatus)),
SLOT(finished(int, QProcess::ExitStatus)));
connect(process_,
SIGNAL(stateChanged(QProcess::ProcessState)),
SLOT(stateChanged(QProcess::ProcessState)));
} //end_ctor(ExternalLauncher)
void Launcher::launch(QString program, QStringList argList)
{
started_ = true;
process_->start(program, argList);
process_->waitForFinished(-1); //(c)
Q_EMIT feedbackLog(process_->readAllStandardOutput());
process_->close();
} //end Launcher::launch()
void Launcher::error(QProcess::ProcessError error)
{
/* just feedback some text about the error */
} //end_slot(Launcher::error)
void Launcher::finished(int exitCode, QProcess::ExitStatus status)
{
started_ = false;
/* feedback some text about finished */
} //end_slot (Launcher::finished)
void Launcher::stateChanged(QProcess::ProcessState state)
{
qDebug() << "Luancher::stateChanged" << state;
}
Wie ich den Launcher:
void MyWidget::createAVI()
{
checkAndDeleteAVI();
launcher_.launch("ffmpeg", "argsList"); //launcher_ defined as class member;
}
So, in (c), ist es unnötig, waitForFinished()? (wie ich gelesen habe einige Infos, die ich sollte nicht zu verwechseln waitForXXX() und signal/slot-framework für QProcess)
Außerdem ist es etwas, das ich verpasst, denn der Launcher-Klasse, wie ich auch Erfahrung in der app-Absturz bei der Verwendung dieses Ansatzes.
zentrale Frage: Im Allgemeinen, wenn Sie anrufen QProcess::terminate() /QProcess::kill(), und wenn zum löschen das QProcess-Objekt?
Dank
InformationsquelleAutor YamHon.CHAN | 2013-04-30
Du musst angemeldet sein, um einen Kommentar abzugeben.
Brauchen Sie nicht zu
waitForFinished()
erhalten Sie das signal über es, warum also warten? Stattdessen möchten Sie vielleichtwaitForStarted()
imlaunch()
um sicher zu sein, dass der Prozess erfolgreich gestartet wurde. Natürlich in diesem Fall müssen Sie ändern die Art, wie Sie IhreLauncher
- nicht zerstören dürfen es nur nachlaunch()
.Brauchen Sie nicht zu
terminate()
/kill()
den Prozess, wenn es fertig ist, nur wenn Sie brauchen, um zu beenden es vorzeitig. Sie können Sie löschen, wenn Sie Sie empfangenfinished()
odererror()
signal mitprocess_->deleteLater()
(man kann nicht einfachdelete process_
während Sie in den Schlitz) oder in Ihrem~Launcher()
, vorausgesetzt, es wird nicht aufgerufen werden, bis der Prozess abgeschlossen ist.InformationsquelleAutor Paul