2

我正在 Qt 中编写代码,其中我使用多个线程 (Qthreads) 以下面代码片段中所示的方式启动命令行进程:

void test_streamer_thread::run()
{
    QProcess    start_process;
    ...

    ret_status = start_process.execute("some_cmd.exe",some_args);
    start_process.close();
}

一旦启动,该进程将无限进行(在 Windows 任务管理器中显示为一个单独的进程)。但是,当应用程序终止时,该进程仍然继续存在。如何确保此进程在启动它的应用程序终止时终止。

4

2 回答 2

3

完全没有必要使用单独的线程来启动进程。

确保在应用程序终止时终止子进程的最简单方法是

QProcess * p = new QProcess(....);
connect(qApp, SIGNAL(aboutToQuit()), process, SLOT(terminate()));

请参阅下面的完整示例。

这种误解就像一种疾病一样传播开来,认为线程是解决每个人问题的方法。我的观察是,在带有标签的 10 个帖子中,有 9 个Qt使用线程是不必要的,并且是不了解问题的结果。

我的规则是:如果你认为你需要使用线程,试着解释它,如果只是在你的脑海里,以说服你的同事。完成此操作后,检查您引用来支持您的论点的所有事实是否确实正确。在许多情况下,它们不是。

下面的示例代码不会捕获 Unix 信号,因此——正如您在 Linux 和 OS X 上会注意到的那样——它只会终止直接后代进程,而不是可能从它启动的任何后续进程。你需要处理 Unix 信号来解决这个问题。

//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"
于 2012-07-10T14:17:15.167 回答
0

看起来您正在分叉一个单独的进程,而不是创建线程。

如果它是一个单独的进程,那么您将需要在父进程和子进程(可能是管道或信号)之间进行某种通信,以告知它应该退出。

如果是线程,则在终止进程后,所有线程都会随之死亡。此外,您不会在 Windows 任务管理器中将线程视为单独的进程(不确定它们将如何显示,但它们不会显示为线程)。

于 2012-07-10T12:37:14.450 回答