本文介绍了我如何使用相同的可执行文件在后台运行3个QProcess的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有Worker类的程序,该类具有3个QProcess es.

I have a program that has a Worker class and this class has 3 QProcesses.

每个进程都需要一个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 loop while(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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 23:56