Qt 新建一个线程,在线程中新建一个进程

前言:

笔者目前正在做一个桌面应用程序,该应用程序的某一个功能已有一个现成的exe很好地实现了,要求在项目中直接使用该exe文件;且因为该功能比较耗时,需要在子线程中进行,所以有这样一个需求:新建一个线程,在线程中新建一个进程调用该exe。

方案选择:

开启线程使用Qt官方推荐的QObject::moveToThread

开启进程使用QProcess类,QProcess类用于启动外部程序并与它们通信。

建议阅读本文代码前先阅读Qt帮助文档的QThread类和QProcess类的Detailed Description部分。

代码实现:

compiler.h

#ifndef COMPILER_H
#define COMPILER_H

#include <QObject>
#include <QProcess>
#include <QThread>

class CompilerWorker : public QObject
{
    Q_OBJECT

public slots:
    void doWork(const QStringList &arguments);

private slots:
    void compilerFinished(int exitCode, QProcess::ExitStatus exitStatus);
    void readStandardOutput();

signals:
    void resultReady(const QString &result);

};

class CompilerController : public QObject
{
    Q_OBJECT
public:
    explicit CompilerController();
    ~CompilerController();

    void sendOperateSignal(const QStringList &);

signals:
    void operate(const QStringList &);
    void threadFinished();

private slots:
    void handleResults(const QString &);

private:
    QThread workerThread;

};

#endif // COMPILER_H

compiler.cpp

#include <QDebug>
#include <QThread>
#include <QProcess>
#include <QTextCodec>
#include <QCoreApplication>

#include "compiler.h"

void CompilerWorker::doWork(const QStringList &arguments)
{
    qDebug() << "receive the execute signal" ;
    qDebug() << "\tCurrent thread ID: " << QThread::currentThreadId();

    //jz 调用编译器进程
    QProcess *cmplProcess = new QProcess;
    QString program = "C:/LdCmpl.exe";

    connect(cmplProcess, &QProcess::readyReadStandardOutput, 
            this, &CompilerWorker::readStandardOutput);

    connect(cmplProcess, SIGNAL(finished(int,QProcess::ExitStatus)), 
            this, SLOT(compilerFinished(int,QProcess::ExitStatus)));

    cmplProcess->start(program, arguments);
    qDebug() << "[Current process ID: " << cmplProcess->processId() << "]";

}

void CompilerWorker::readStandardOutput()
{
    QProcess *process = qobject_cast<QProcess *>(sender());
    QTextCodec *codec = QTextCodec::codecForLocale();
    QString str = codec->toUnicode(process->readAllStandardOutput());
    qDebug() << str;
}

void CompilerWorker::compilerFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    qDebug() << "Ldcmpl.exe process finish." << exitCode << exitStatus;
    qDebug() << "\tFinish the work and sent the result Ready signal\n" ;
    emit resultReady("result...");
}

//---------------------------------------------------------------------------------------

CompilerController::CompilerController()
{
    CompilerWorker *compiler = new CompilerWorker;
    compiler->moveToThread(&workerThread); //jz △△

    connect(&workerThread, &QThread::finished, compiler, &QObject::deleteLater);

    connect(this, &CompilerController::operate, compiler, &CompilerWorker::doWork);

    connect(compiler, &CompilerWorker::resultReady, this, &CompilerController::handleResults);

    workerThread.start();
}


CompilerController::~CompilerController()
{
    qDebug() << "!!!!!!~CompilerController()";
    workerThread.quit();
    workerThread.wait();
}

void CompilerController::sendOperateSignal(const QStringList &arguments)
{
    //jz 发信号通知开始
    qDebug() << "\nemit the signal to execute!" ;
    qDebug() << "\tCurrent thread ID:" << QThread::currentThreadId() << '\n' ;
    emit operate(arguments);
}

void CompilerController::handleResults(const QString &result)
{
    qDebug() << "receive the resultReady signal" ;
    qDebug() << "\tCurrent thread ID: " << QThread::currentThreadId();
    qDebug() << "\tThe result is: " << result ;

    emit threadFinished();
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>

class QPushButton;
class CompilerController;

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void clickSlot();

private:
    QPushButton *pushButton;
    CompilerController *compilerController = NULL;
};

#endif // WIDGET_H

widget.cpp

#include "widget.h"

#include <QDebug>
#include <QPushButton>
#include <QCoreApplication>

#include "compiler.h"

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    this->resize(400, 300);
    pushButton = new QPushButton(this);
    pushButton->setText("PushButton");
    pushButton->show();
    connect(pushButton, &QPushButton::clicked, this, &Widget::clickSlot);
}

Widget::~Widget()
{
    if (compilerController != NULL)
    {
        delete compilerController;
    }
}

void Widget::clickSlot()
{
    qDebug() << "[main process ID: " << QCoreApplication::applicationPid() << "]\n";

    compilerController = new CompilerController;

    connect(compilerController, &CompilerController::threadFinished, this, [ = ]()
    {
        delete compilerController;
        compilerController = NULL;
    });

    QStringList arguments;
    arguments << "C:/src.LD2" << "C:/dest.LD2.txt";
    compilerController->sendOperateSignal(arguments);
}



main.cpp

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

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值