问题描述
我有一个具有Worker
类的程序,该类具有3个QProcess
es.
I have a program that has a Worker
class and this class has 3 QProcess
es.
每个进程都需要一个QDate
作为参数.我想在后台运行所有这些程序.
Each process will require a QDate
as an argument.I want to run all of them in background.
问题
如果我尝试指定3个以上的日期(表示所有进程都在运行),整个程序冻结.
If I try to specify more than 3 dates (meaning all processes are running),the entire program freezes.
我已经尝试使用QProcess::startDetached
,但是会弹出我不喜欢的命令提示符.
I've already tried using QProcess::startDetached
but it pops up command prompts which I don't like.
我希望所有内容都在后台运行,三个进程同时运行.
I want everything to run in background, 3 processes running simultaneously.
这是我的代码:
在 worker.h
in worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QDate>
#include <QProcess>
#include <QQueue>
class Worker: public QObject
{
Q_OBJECT
signals:
void processed(QString& date);
void error(QString& error);
void done(QString& done);
public:
Worker();
void run(QDate& start, QDate& end, int delay);
private slots:
void onFinished1(int exitCode, QProcess::ExitStatus exitStatus);
void onError1(QProcess::ProcessError);
void onFinished2(int exitCode, QProcess::ExitStatus exitStatus);
void onError2(QProcess::ProcessError);
void onFinished3(int exitCode, QProcess::ExitStatus exitStatus);
void onError3(QProcess::ProcessError);
private:
QProcess* worker1;
QProcess* worker2;
QProcess* worker3;
QQueue<QDate> date_list;
int running;
};
#endif // WORKER_H
在 worker.cpp
in worker.cpp
#include "worker.h"
#include <QDebug>
#include <QStringList>
Worker::Worker()
{
worker1 = new QProcess(this);
worker2 = new QProcess(this);
worker3 = new QProcess(this);
connect(worker1, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(onFinished1(int,QProcess::ExitStatus)));
connect(worker1, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(onError1(QProcess::ProcessError)));
connect(worker2, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(onFinished2(int,QProcess::ExitStatus)));
connect(worker2, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(onError2(QProcess::ProcessError)));
connect(worker3, SIGNAL(finished(int,QProcess::ExitStatus)),
this, SLOT(onFinished3(int,QProcess::ExitStatus)));
connect(worker3, SIGNAL(error(QProcess::ProcessError)),
this, SLOT(onError3(QProcess::ProcessError)));
running = 0;
}
void
Worker::onFinished1(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug() << "worker 1: "
<< "Exit Code: " << exitCode
<< "Exit Status: " << exitStatus;
running -= 1;
if (date_list.empty() && running == 0) {
//system("rm output.xlsx");
system("copy .\\extractor\\output.xlsx output.xlsx");
emit done(QString("Done generating output.xlsx"));
}
}
void
Worker::onFinished2(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug() << "worker 2: "
<< "Exit Code: " << exitCode
<< "Exit Status: " << exitStatus;
running -= 1;
if (date_list.empty() && running == 0) {
//system("rm output.xlsx");
system("copy .\\extractor\\output.xlsx output.xlsx");
emit done(QString("Done generating output.xlsx"));
}
}
void
Worker::onFinished3(int exitCode, QProcess::ExitStatus exitStatus)
{
qDebug() << "worker 3: "
<< "Exit Code: " << exitCode
<< "Exit Status: " << exitStatus;
running -= 1;
if (date_list.empty() && running == 0) {
//system("rm output.xlsx");
system("copy .\\extractor\\output.xlsx output.xlsx");
emit done(QString("Done generating output.xlsx"));
}
}
void
Worker::onError1(QProcess::ProcessError /* error */)
{
qDebug() << "worker 1: "
<< "Error: " << worker1->errorString();
running -= 1;
emit error(worker1->errorString());
}
void
Worker::onError2(QProcess::ProcessError /* error */)
{
qDebug() << "worker 2: "
<< "Error: " << worker2->errorString();
running -= 1;
emit error(worker2->errorString());
}
void
Worker::onError3(QProcess::ProcessError /* error */)
{
qDebug() << "worker 3: "
<< "Error: " << worker3->errorString();
running -= 1;
emit error(worker3->errorString());
}
void
Worker::run(QDate& start, QDate& end, int delay)
{
qDebug() << __FUNCTION__
<< start
<< end
<< delay;
while(start <= end) {
date_list.push_back(start);
start = start.addDays(1);
}
QProcess * current;
QDate processed_date;
QStringList args;
qDebug() << date_list;
while(! date_list.empty()) {
bool has_available = false;
if (worker1->state() != QProcess::Running) {
current = worker1;
processed_date = date_list.dequeue();
has_available = true;
} else if (worker2->state() != QProcess::Running) {
current = worker2;
processed_date = date_list.dequeue();
has_available = true;
} else if (worker3->state() != QProcess::Running) {
current = worker3;
processed_date = date_list.dequeue();
has_available = true;
}
// Has available worker, start worker
if (has_available) {
running += 1;
QString sdate = processed_date.toString("yyyy-MM-dd");
args << sdate << QString::number(delay);
current->start(".\\release\\extractor\\content.exe", args);
args.clear();
emit processed(sdate);
}
qDebug() << "running: " << running;
}
}
有什么想法吗?
推荐答案
您的程序由于一直忙于等待QProcess
(即while(1)
)完成而冻结.因此,在处理所有日期之前,您不会返回主事件循环.如果等待足够长的时间,您的程序将解冻.
Your program freezes because it is busy all the time with waiting on QProcess
to be finished, i.e. while(1)
. So, you do not return to the main event loop before all your dates are processed. If you wait long enough, your program will unfreeze.
存在不同的解决方案:
-
使用
finished
事件开始处理新日期(直到列表为空),即删除无限/等待循环while(1)
.
Use the
finished
event to start processing a new date (until the list is empty), i.e. remove the infinite/waiting loopwhile(1)
.
在单独的线程中执行Worker::run
.
调用 QCoreApplication::processEvents
进行处理待处理事件,例如has_available
为false时.
Call QCoreApplication::processEvents
to process the pending events, for example when has_available
is false.
请注意,我更喜欢第一个解决方案,因为Qt是事件驱动系统.
这篇关于我如何使用相同的可执行文件在后台运行3个QProcess的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!