Qt 运行多组QProcess';接二连三

Qt 运行多组QProcess';接二连三,qt,asynchronous,polling,qprocess,Qt,Asynchronous,Polling,Qprocess,我需要调用外部程序N多次。我想同时做这件事。因此,到目前为止,我的策略是启动Nq进程,并对已启动和已完成的进程进行计数。(这样我就能知道他们什么时候都完成了) 但是,外部程序占用了相当多的RAM,因此我不希望在任何时候有更多的4个并行进程 这方面的好策略是什么 我认为信号/插槽不足以实现这一点(我想不出一种不太复杂的方法)…也许我可以用队列做些什么 如何确保一次只运行4个进程? 然后,我如何确定所有N进程最终何时完成 (PySt/Pyqt的答案优先,但C++是OK)< /P> < P>概念证明:

我需要调用外部程序
N
多次。我想同时做这件事。因此,到目前为止,我的策略是启动
N
q进程,并对已启动和已完成的进程进行计数。(这样我就能知道他们什么时候都完成了)

但是,外部程序占用了相当多的RAM,因此我不希望在任何时候有更多的4个并行进程

这方面的好策略是什么

我认为信号/插槽不足以实现这一点(我想不出一种不太复杂的方法)…也许我可以用队列做些什么

如何确保一次只运行4个进程? 然后,我如何确定所有
N
进程最终何时完成

(PySt/Pyqt的答案优先,但C++是OK)< /P> < P>概念证明:

h文件

#ifndef CPROCESSRUNNER_H
#define CPROCESSRUNNER_H

#include <QObject>
#include <QQueue>

class QProcess;

class CProcessRunner : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int processCount READ processCount WRITE setProcessCount)
public:
    explicit CProcessRunner(QObject *parent = 0);
    ~CProcessRunner();

    void addProcess(const QString& program);

    int processCount() const;

public slots:
    void setProcessCount(int arg);

private slots:
    void startFreeProcesses();

private:
    int getActiveProcessCount() const;

    QQueue<QProcess*> m_processes;
    int m_processCount;
};

#endif // CPROCESSRUNNER_H
\ifndef CPROCESSRUNNER\u H
#定义CPROCESSRUNNER\u H
#包括
#包括
类QProcess;
CProcessRunner类:公共QObject
{
Q_对象
Q_属性(int processCount READ processCount WRITE setProcessCount)
公众:
显式CProcessRunner(QObject*parent=0);
~cprocesrunner();
无效添加过程(常量字符串和程序);
int processCount()常量;
公众时段:
void setProcessCount(int arg);
专用插槽:
void startfreeprocesss();
私人:
int getActiveProcessCount()常量;
qm_过程;
int m_进程计数;
};
#endif//CPROCESSRUNNER\u H
cpp文件

#include "CProcessRunner.h"
#include <QProcess>
CProcessRunner::CProcessRunner(QObject *parent)
    : QObject(parent)
    , m_processCount(0)
{

}

CProcessRunner::~CProcessRunner()
{

}

void CProcessRunner::addProcess(const QString& program)
{
    QProcess* pProcess = new QProcess(this);
    pProcess->setObjectName(program);
    m_processes.enqueue(pProcess);
    startFreeProcesses();
}

int CProcessRunner::processCount() const
{
    return m_processCount;
}

void CProcessRunner::setProcessCount(int arg)
{
    m_processCount = arg;
}

void CProcessRunner::startFreeProcesses()
{
    while (!m_processes.isEmpty() && (getActiveProcessCount() < m_processCount)) {
        QProcess* pProcess = m_processes.dequeue();
        connect(pProcess, SIGNAL(finished(int)), this, SLOT(startFreeProcesses()));
        connect(pProcess, SIGNAL(finished(int)), pProcess, SLOT(deleteLater()));

        pProcess->start(pProcess->objectName());
        pProcess->waitForStarted(-1);
    }
}

int CProcessRunner::getActiveProcessCount() const
{
    int result = 0;
    foreach (QProcess* pProcess, findChildren<QProcess*>()) {
        if (pProcess->state() == QProcess::Running) {
            result++;
        }
    }
    return result;
}
#包括“cprocesrunner.h”
#包括
CProcessRunner::CProcessRunner(QObject*父对象)
:QObject(父对象)
,m_processCount(0)
{
}
CProcessRunner::~CProcessRunner()
{
}
void CProcessRunner::addProcess(常量QString和程序)
{
QProcess*pProcess=新的QProcess(此);
p进程->设置对象名称(程序);
m_进程排队(pProcess);
startfreeprocesss();
}
int CProcessRunner::processCount()常量
{
返回m_processCount;
}
void CProcessRunner::setProcessCount(int arg)
{
m_processCount=arg;
}
void CProcessRunner::startfreeprocesss()
{
而(!m_processs.isEmpty()&&(getActiveProcessCount()start(pProcess->objectName());
p进程->等待开始(-1);
}
}
int CProcessRunner::getActiveProcessCount()常量
{
int结果=0;
foreach(QProcess*ppprocess,findChildren()){
如果(pProcess->state()==QProcess::Running){
结果++;
}
}
返回结果;
}

以下是我当前使用Pyside的实现,仅供参考。 我希望能够捕获每个进程的输出并将其传递(用于显示在
QTextEdit
或类似文件中)。为此,我为每个进程分配了一个编号,并将它的stdout和stderr连接到插槽,然后插槽将发出消息和进程位置。 我不相信我目前对该功能的实现,但下面是:

class ProcessRunner(QtCore.QObject):  
'''
Runs N processes in groups of M
'''    

singleProcessFinished = QtCore.Signal()
error = QtCore.Signal(tuple) #(process number, message)
message = QtCore.Signal(tuple) #(process number, message)

def __init__(self, maxProcesses=4, parent=None):
  super(ProcessRunner, self).__init__(parent)
  self.processQueue = Queue.Queue()  
  self.maxProcesses = maxProcesses
  self.activeProcessCount = 0

  self._processNumber = 0

def addProcess(self, program, args):
  '''
  Add a process to the process queue

  Args:

    program (str): String of program path and arguments, separated by one or more spaces    
  '''
  self._processNumber += 1
  if self._processNumber == self.maxProcesses:
    self._processNumber = 0


  proc = QtCore.QProcess(self)
  proc.readyReadStandardError.connect(lambda pos=self._processNumber, process=proc: self.emit_error(pos, proc))
  proc.readyReadStandardOutput.connect(lambda pos=self._processNumber, process=proc: self.emit_output(pos, proc))
  self.processQueue.put((proc, program, args))
  self.startFreeProcesses()

def startFreeProcesses(self):
  '''
  Starts all waiting processes up to a maximum of self.maxProcesses
  '''
  while (not self.processQueue.empty()) and (self.activeProcessCount < self.maxProcesses):
    proc, program, args = self.processQueue.get()
    proc.finished.connect(self.startFreeProcesses)
    proc.finished.connect(proc.deleteLater)
    proc.finished.connect(self.singleProcessFinished.emit)
    proc.finished.connect(self._decreaseActiveProcessCount)

    proc.start(program, args)
    proc.waitForStarted(-1)
    self._increaseActiveProcessCount()

def _decreaseActiveProcessCount(self):
  self.activeProcessCount -= 1

def _increaseActiveProcessCount(self):
  self.activeProcessCount += 1

def emit_error(self, pos, proc):    
  self.error.emit(pos, str(proc.readAllStandardError()))

def emit_error(self, pos, proc):    
  self.error.emit(pos, str(proc.readAllStandardOutput()))
类ProcessRunner(QtCore.QObject): ''' 以M为一组运行N个进程 ''' singleProcessFinished=QtCore.Signal() 错误=QtCore.Signal(元组)#(进程号,消息) message=QtCore.Signal(元组)#(进程号,消息) def uuu init uuuu(self,maxprocess=4,parent=None): 超级(ProcessRunner,self)。\uuuuu初始化\uuuuuu(父级) self.processQueue=Queue.Queue() self.maxprocess=maxprocess self.activeProcessCount=0 self.\u processNumber=0 def addProcess(自身、程序、参数): ''' 将进程添加到进程队列 Args: 程序(str):程序路径和参数的字符串,由一个或多个空格分隔 ''' self.\u processNumber+=1 如果self.\u processNumber==self.maxprocess: self.\u processNumber=0 proc=QtCore.QProcess(self) proc.readyReadStandardError.connect(lambda pos=self.\u processNumber,process=proc:self.emit\u error(pos,proc)) proc.readyReadStandardOutput.connect(lambda pos=self.\u processNumber,process=proc:self.emit\u output(pos,proc)) self.processQueue.put((进程、程序、参数)) self.startfreeprocesss() def STARTFREEPROCESS(自): ''' 启动所有等待进程,最多可启动self.maxprocess ''' 而(不是self.processQueue.empty())和(self.activeProcessCount这看起来是一个非常好的开始。我们如何知道所有流程何时完成?我想在调用函数中,您可以在(process\u runner.getActiveProcessCount()>0)继续时放入类似于
的内容,
…这样最好吗?您可以签入startFreeProcesss是getActiveProcessCount等于零。完成后,您将检查每个进程是否已完成所有进程。
m_processCount
应重命名为
m_maxAsyncProcessCount
,或类似名称。除此之外,看起来很棒,而且完成了任务!你的答案不加修改是行不通的。StartFreeProcesss()中的循环永远无法运行,因为m_processCount从未递增。我添加了行setProcessCount(processCount()+1);正在进行中。然后在startFreeProcess中,decr