QThread/QProcess 问题:进程不会终止并发生崩溃

问题描述 投票:0回答:1

目前,我正在学习QThread和QProcess,所以我想制作一个进程监控demo。但是,我遇到了两个无法解决的问题。

问题:

QProcess 可以成功启动一个进程(例如 cmd.exe),但是当我调用 stopProcess() 时,出现两个错误,或者有时主进程崩溃。

错误:

QProcess: Destroyed while process ("cmd.exe") is still running.
QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread.

使用 ProcessId() 获取进程 ID 后,我尝试使用 taskkill 命令终止它。但是,如果没有 /F 参数,我收到以下错误:

Error: Unable to terminate process 18668.
Reason: This process can only be forcefully terminated (use the /F option).

这是我的代码。您能帮我审核一下吗?谢谢!

主.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

主窗口.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include "processmonitor.h"

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    ProcessMonitor *pm;

    void setupConnection();

private slots:
    void handleReadyReadStandardOutput(const QString& data);
    void handleReadyReadStandardError(const QString& data);
    void handleStarted(const QString& message);
    void handleStateChanged(QProcess::ProcessState newState);
    void handleStopped(const QString& message);

    void on_start_process_clicked();
    void on_stop_process_clicked();
};
#endif // MAINWINDOW_H

主窗口.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), pm(new ProcessMonitor)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    if(!pm) {
        qDebug() << "ProcessMonitor Start Failed,Exit!";
        QApplication::quit();
    }
    setupConnection();

}

MainWindow::~MainWindow()
{
    if(pm) {
        pm->stopProcess();
        delete pm;
    }
    delete ui;
}

void MainWindow::setupConnection() {
    connect(pm, &ProcessMonitor::readyReadStandardOutput, this, &MainWindow::handleReadyReadStandardOutput);
    connect(pm, &ProcessMonitor::readyReadStandardError, this, &MainWindow::handleReadyReadStandardError);
    connect(pm, &ProcessMonitor::started, this, &MainWindow::handleStarted);
    connect(pm, &ProcessMonitor::stateChanged, this, &MainWindow::handleStateChanged);
    connect(pm, &ProcessMonitor::stopped, this, &MainWindow::handleStopped);
}

// 'outInfo' component is a QPlainTextEdit
void MainWindow::handleReadyReadStandardOutput(const QString& data){
    this->ui->outInfo->appendPlainText(data);
}

void MainWindow::handleReadyReadStandardError(const QString& data){
    this->ui->outInfo->appendPlainText("Error:" + data );
}

// 'selfInfo' component is a QPlainTextEdit
void MainWindow::handleStarted(const QString& message){
    this->ui->selfInfo->appendPlainText(message);
}

void MainWindow::handleStateChanged(QProcess::ProcessState newState) {
    QString stateString;
    switch(newState) {
    case QProcess::NotRunning:
        stateString = "Not Running";
        break;
    case QProcess::Starting:
        stateString = "Starting";
        break;
    case QProcess::Running:
        stateString = "Running";
        break;
    default:
        stateString = "Unknown State";
        break;
    }
    this->ui->selfInfo->appendPlainText("State Changed: " + stateString);
}


void MainWindow::handleStopped(const QString& message){
    this->ui->selfInfo->appendPlainText(message);
}

void MainWindow::on_start_process_clicked()
{
    this->pm->start();
}

void MainWindow::on_stop_process_clicked()
{
    this->pm->stopProcess();
}

processmonitor.h

#ifndef PROCESSMONITOR_H
#define PROCESSMONITOR_H

#include <QThread>
#include <QProcess>
#include <QDebug>

class ProcessMonitor : public QThread
{
    Q_OBJECT
public:
    ProcessMonitor();
    ~ProcessMonitor();

    void run() override;
    void stopProcess();

signals:
    void readyReadStandardOutput(QString output);
    void readyReadStandardError(QString error);
    void started(QString message);
    void stateChanged(QProcess::ProcessState newState);
    void stopped(QString message);

private:
    QProcess *process;

private slots:
    void handleReadyReadStandardOutput();
    void handleReadyReadStandardError();
    void handleStarted();
    void handleStateChanged(QProcess::ProcessState newState);
};

#endif // PROCESSMONITOR_H

进程监视器.cpp

#include "processmonitor.h"

ProcessMonitor::ProcessMonitor()
    : process(nullptr)
{
}

ProcessMonitor::~ProcessMonitor() {
    stopProcess(); // Stop the process before destruction
}

void ProcessMonitor::run() {
    if (this->process) {
        delete this->process;
    }
    this->process = new QProcess();
    if (!this->process) {
        qDebug() << "Error: unable to instantiate QProcess";
        return;
    }
    // this->process->setWorkingDirectory("E:\\test"); // set work dir

    connect(this->process, &QProcess::readyReadStandardOutput, this, &ProcessMonitor::handleReadyReadStandardOutput);
    connect(this->process, &QProcess::readyReadStandardError, this, &ProcessMonitor::handleReadyReadStandardError); 
    connect(this->process, &QProcess::started, this, &ProcessMonitor::handleStarted);
    connect(this->process, &QProcess::stateChanged, this, &ProcessMonitor::handleStateChanged);

    this->process->start("cmd.exe");
    qDebug() << "ProcessID:" << this->process->processId();
    this->exec();
}

void ProcessMonitor::stopProcess() {
    if (!this->process) {
        emit stopped("[ProcessMonitor] No Process Created");
        return;
    }

    // this->process->close();
    this->process->terminate();
    // this->process->kill();

    if (this->process->waitForFinished(3000)) {
        emit stopped("[ProcessMonitor] Process Stopped");
    } else {
        this->process->kill();
        emit stopped("[ProcessMonitor] Process terminated failed, Killing");
    }

    delete this->process;  // Release the pointer after a safety check
    this->process = nullptr;
    this->quit();
}

void ProcessMonitor::handleReadyReadStandardOutput() {
    if (!this->process) return;
    QByteArray data = this->process->readAllStandardOutput();
    emit readyReadStandardOutput(QString::fromLocal8Bit(data));
}

void ProcessMonitor::handleReadyReadStandardError() {
    if (!this->process) return;
    QByteArray data = this->process->readAllStandardError();
    emit readyReadStandardError(QString::fromLocal8Bit(data));
}

void ProcessMonitor::handleStarted() {
    emit started("[ProcessMonitor] Process Started");
}

void ProcessMonitor::handleStateChanged(QProcess::ProcessState newState) {
    emit stateChanged(newState);
}

我尝试在 process->terminate() 之前调用 process->close(),但仍然出现此错误。有时,主进程也会崩溃。

QWinEventNotifier: Event notifiers cannot be enabled or disabled from another thread
c++ qt qthread qprocess
1个回答
0
投票

尝试:

process.terminate();
if (!process.waitForFinished(5000)) { // Timeout di 5 secondi
    process.kill(); // Forza l'arresto se non termina in tempo
}

然后检查:

connect(&process, &QProcess::finished, [](int exitCode, QProcess::ExitStatus exitStatus) {
    qDebug() << "Process terminated with code:" << exitCode
             << "Status:" << exitStatus;
});
© www.soinside.com 2019 - 2024. All rights reserved.