使用單獨的線程來啓動進程是完全沒有必要的。
確保子進程的最簡單方式被終止時,應用程序終止將
QProcess * p = new QProcess(....);
connect(qApp, SIGNAL(aboutToQuit()), process, SLOT(terminate()));
一個完整的例子見下文。
有這種誤解正在像疾病一樣蔓延,線索是解決所有人問題的方法。我的觀察結果是,在使用Qt
標籤的10篇文章中,有9篇不需要使用線程,這是不理解問題的結果。
我的規則是:如果你認爲你需要使用線程,試着解釋它,如果只是在你的腦海中,說服你的同事。做完這件事後,檢查一下你引用的所有事實來支持你的觀點其實都是事實。在很多情況下,他們不是。
下面的示例代碼沒有捕獲到Unix信號,所以 - 你會注意到在Linux和OS X上 - 它只會終止直接後代進程,而不是任何可能從它啓動的後續進程。你會need to handle Unix signals來解決這個問題。
//main.cpp
#include <QApplication>
#include <QPushButton>
#include <QProcess>
class Launcher : public QObject
{
Q_OBJECT
int n;
QProcess * process;
signals:
void setDisabled(bool);
public slots:
void launch() {
QStringList args;
args << QString::number(n);
process = new QProcess(this);
process->start(QCoreApplication::applicationFilePath(), args);
connect(qApp, SIGNAL(aboutToQuit()), process, SLOT(terminate()));
emit setDisabled(true);
}
public:
Launcher(int no) : n(no), process(0) {}
~Launcher() {
if (process) {
process->terminate();
process->waitForFinished();
}
}
};
int main(int argc, char ** argv)
{
QApplication a(argc, argv);
int n = 0;
if (argc > 1) n = QByteArray(argv[1]).toInt();
Launcher launcher(n+1);
QPushButton spawn(QString("Spawn #%1").arg(n));
launcher.connect(&spawn, SIGNAL(clicked()), SLOT(launch()));
spawn.connect(&launcher, SIGNAL(setDisabled(bool)), SLOT(setDisabled(bool)));
spawn.show();
return a.exec();
}
#include "main.moc"