メインスレッドで時間のかかる操作を実行することを避けるために、Qt のスレッド モデルを使用して MyProcess クラスを別のスレッドで実行できます。これにより、メインスレッドで `process.waitForFinished()` が実行され、プログラムの応答がブロックされることが回避されます。
QObject から MyProcess クラスを継承し、その `run()` 関数をオーバーロードし、プログラムの起動および待機操作をこの関数に配置しました。
Processor クラスでは、新しいスレッドを作成し、MyProcess クラスのインスタンスをこのスレッドに移動し、`start()` メソッドを呼び出してプログラムの実行を開始します。同時に、信号とスロットを使用して OutputReady 信号とスロット関数を接続し、プログラムの出力内容のリアルタイム出力を実現します。`processFinished` シグナルは、プログラムの実行の終了を通知するために使用されます。
最後にmain関数内でProcessorインスタンスを新規作成し、slot関数に接続することでプログラムの出力内容とプログラムの実行終了情報を出力します。
これにより、MyProcess クラスの実行プロセスが別スレッドに移動され、スレッド分離と非同期実行が実現され、マルチコア CPU 上でのプログラムの実行効率が向上し、メインスレッドでの時間のかかる実行が回避されます。この操作によりプログラムがブロックされます。
#include <QCoreApplication>
#include <QtCore>
#include <QThread>
class MyProcess : public QProcess {
Q_OBJECT
public:
MyProcess() {
connect(this, &MyProcess::readyReadStandardOutput, [=](){
QByteArray output = this->readAllStandardOutput();
//QByteArray转QString并移除结尾的换行符
QString text(output);
text.chop(1);
emit outputReady(text);
});
}
void terminateProcess() {
if (state() != QProcess::NotRunning) {
terminate(); // 发送SIGTERM信号
waitForFinished(); // 等待进程终止
}
}
signals:
void outputReady(const QString &output); //程序输出信号
public:
void run() {
start("ping 192.168.2.1 -c 10"); //启动程序
while(state() != QProcess::NotRunning){
emit processEvents(); //触发事件循环,处理传入的事件
msleep(100); //降低循环速度
}
emit processFinished(); //通知进程结束
}
protected:
void msleep(int ms) { //眠函数
QThread::msleep(ms);
}
void processEvents() { //处理事件函数
QCoreApplication::processEvents();
}
signals:
void processFinished();
};
class Processor : public QObject {
Q_OBJECT
public:
Processor() {
//建立线程
thread = new QThread(this);//建立MyProcess实例
myProcess = new MyProcess;
//将myProcess移动到线程中
myProcess->moveToThread(thread);
//建立线程启动信号和槽的连接
connect(thread, &QThread::started, myProcess, &MyProcess::run);
//建立程序输出信号和槽的连接
connect(myProcess, &MyProcess::outputReady, this, &Processor::outputReady);
//建立进程结束信号和槽的连接
connect(myProcess, &MyProcess::processFinished, this, &Processor::processFinished);
//启动线程
thread->start();
}~Processor() {
//结束线程
thread->quit();
thread->wait();
}
signals:
void outputReady(const QString &output);
void processFinished();
private:
QThread *thread;
MyProcess *myProcess;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Processor processor;
QObject::connect(&processor, &Processor::outputReady, [](const QString &output){
qDebug() << output; //输出程序的输出内容
});QObject::connect(&processor, &Processor::processFinished, [](){
qDebug() << "程序执行结束";
});
return a.exec();
}
#include "main.moc"
このプログラムが任意のコンソール プログラムを起動して実行できるようにするには、実行するコンソール プログラムとその引数リストを受け入れるパラメーターを追加します。そして、これらのパラメータをコンソール プログラムに渡せるように、MyProcess クラスの `start()` 関数を適宜変更します。
変更されたコードは次のとおりです。
#include <QCoreApplication>
#include <QtCore>
#include <QThread>
class MyProcess : public QProcess {
Q_OBJECT
public:
MyProcess(const QString &cmd, const QStringList &args) {
connect(this, &MyProcess::readyReadStandardOutput, [=](){
QByteArray output = this->readAllStandardOutput();
//QByteArray转QString并移除结尾的换行符
QString text(output);
text.chop(1);
emit outputReady(text);
});
setProgram(cmd);
setArguments(args);
}
void terminateProcess() {
if (state() != QProcess::NotRunning) {
terminate(); // 发送SIGTERM信号
waitForFinished(); // 等待进程终止
}
}
signals:
void outputReady(const QString &output); //程序输出信号
public:
void run() {
start(); //启动程序
while(state() != QProcess::NotRunning){
emit processEvents(); //触发事件循环,处理传入的事件
msleep(100); //降低循环速度
}
emit processFinished(); //通知进程结束
}
protected:
void msleep(int ms) {
//眠函数
QThread::msleep(ms);
}
void processEvents() { //处理事件函数
QCoreApplication::processEvents();
}
signals:
void processFinished();
};
class Processor : public QObject {
Q_OBJECT
public:
Processor(const QString &cmd, const QStringList &args) {
//建立线程
thread = new QThread;
//建立MyProcess实例
myProcess = new MyProcess(cmd, args);
//将myProcess移动到线程中
myProcess->moveToThread(thread);
//建立线程启动信号和槽的连接
connect(thread, &QThread::started, myProcess, &MyProcess::run);
//建立程序输出信号和槽的连接
connect(myProcess, &MyProcess::outputReady, this, &Processor::outputReady);
//建立进程结束信号和槽的连接
connect(myProcess, &MyProcess::processFinished, this, &Processor::processFinished);
//启动线程
thread->start();
}
~Processor() {
//结束线程
thread->quit();
thread->wait();
}
signals:
void outputReady(const QString &output);
void processFinished();
private:
QThread *thread;
MyProcess *myProcess;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QString cmd = "ping";
QStringList args = {"192.168.2.1", "-c", "10"};
Processor processor(cmd, args);
QObject::connect(&processor, &Processor::outputReady, [](const QString &output){
qDebug() << output; //输出程序的输出内容
});
QObject::connect(&processor, &Processor::processFinished, [](){
qDebug() << "程序执行结束";
});
return a.exec();
}
#include "main.moc"
この変更されたコードでは、コンソール プログラムとそのパラメーター リストを受け入れるための `MyProcess` のコンストラクターを追加し、それをそれに応じて `QProcess` に設定しました。