QProcess readyRead before started

Posted

技术标签:

【中文标题】QProcess readyRead before started【英文标题】: 【发布时间】:2013-04-28 13:07:33 【问题描述】:

我是第一次使用QProcess,在试验时我注意到readyReadstarted 之前发出信号。

我尝试使用QProcess 运行/usr/bin/echo foobar,并将两个函数附加到readyRead()started() 信号,然后按以下顺序输出:

    使用 start() 方法启动进程 dataReady() 信号 started() 信号

现在,我发现started()dataReady()之后有点奇怪,因为通常一个进程进入运行状态之前它实际上可以产生数据,但我找不到任何关于文档中的这个顺序,也许这是完全合乎逻辑的,但是......有人可以解释一下为什么会发生这种情况吗?

编辑: 我在这里添加了一个行为就像我说的那样的代码。我使用的是 Qt 4.8.4 64 位。

/*****************************************************************************/
// multiproc.hh
#ifndef MULTIPROC_HH
#define MULTIPROC_HH

#include <QObject>
#include <QtCore>
#include <iostream>
#include "node.hh"

class MultiProc: public QObject 
    Q_OBJECT
public:
    MultiProc(QObject *parent = 0):
        QObject(parent) 
        std::cout << "MultiProc\n";

        QList<QStringList> args;
        args << (QStringList() << "/usr/bin/echo" << "Proc 0 running");
        args << (QStringList() << "/usr/bin/echo" << "Proc 1 running");
        args << (QStringList() << "/usr/bin/cat");
        args << (QStringList() << "/usr/bin/cat");
        args << (QStringList() << "/usr/bin/tee" << "/etc/hostname");

        for (int i = 0; i < args.size(); ++i)
            _nodes << new Node(this, i, args[i]);
    
signals:
    void finished();
public slots:
    void run() 
        std::cout << "Starting all nodes :)\n";
        foreach (Node *n, _nodes)
            n->start();
    
private:
    QList<Node *> _nodes;
;

#endif // MULTIPROC_HH

/*****************************************************************************/
// node.hh
#ifndef NODE_HH
#define NODE_HH

#include <QtCore>
#include <iostream>

class Node: public QObject 
    Q_OBJECT
public:
    Node(QObject *parent, int id, const QStringList &args):
        QObject(parent),
        _id(id),
        _proc(new QProcess(this)),
        _args(args) 
        std::cout << "Node " << _id << " created with command "
                  << args.join(" ").toStdString() << "\n";
        connect(_proc, SIGNAL(started()), this, SLOT(started()));
        connect(_proc, SIGNAL(finished(int)), this, SLOT(finished()));
        connect(_proc, SIGNAL(readyRead()), this, SLOT(readyRead()));
        connect(_proc, SIGNAL(error(QProcess::ProcessError)),
                this, SLOT(error(QProcess::ProcessError)));
    
    void start() 
        if (_proc->state() == QProcess::NotRunning) 
            std::cout << "Starting process on node: " << _id << "\n";
            _proc->start(_args.at(0), _args.mid(1));
        
    
public slots:
    void started()  std::cout << "Node " << _id << " started\n"; 
    void finished()  std::cout << "Node " << _id << " finished\n"; 
    void readyRead()  std::cout << "Node " << _id << " readyRead\n"; 
    void error(QProcess::ProcessError err) 
        std::cout << "Node " << _id << " Error: " << err << "\n";
        QCoreApplication::exit(1);
    
private:
    int _id;
    QProcess *_proc;
    QStringList _args;
;

#endif // NODE_HH

/*****************************************************************************/
// main.cpp
#include <QCoreApplication>
#include "multiproc.hh"

int main(int argc, char *argv[]) 
    QCoreApplication a(argc, argv);

    MultiProc *p = new MultiProc(&a);
    QObject::connect(p, SIGNAL(finished()), &a, SLOT(quit()));
    QTimer::singleShot(0, p, SLOT(run()));
    return a.exec();

这里有一段输出:

Node 0 readyRead
Node 2 started
Node 0 started
Node 0 finished
Node 1 started
Node 1 readyRead
Node 4 started
Node 1 finished
Node 3 started

【问题讨论】:

无法重现,我认为这根本不合逻辑。 这对我来说似乎也不合逻辑:S 我会尽快隔离它,看看它是 Qt 问题还是什么。 【参考方案1】:

我可以在 Linux 和 Qt 5.0.1 上通过首先启动进程然后连接信号来重现此问题:

process.start("echo foo", QIODevice::ReadWrite);

connect(&process, SIGNAL(started()), this, SLOT(started()));
connect(&process, SIGNAL(readyReadStandardOutput()), this, SLOT(readyRead()));

但是,如果我先连接信号然后启动进程,则会首先调用 started() 插槽作为例外。

您发现的功能可能被视为错误,您可能需要将其报告给Qt bug tracker。

编辑:

我能够用您的代码重现问题。我还可以通过对 Node 的 start() 函数进行一些小改动来修复它。在调用start() 之后,在继续之前调用waitForStarted()。请注意,仅当进程状态为QProcess::Starting 时才等待,这样可以避免尝试启动不存在的程序时出现问题。在那种情况下,该过程将永远不会开始。当然,也可以通过为 waitForStarted 函数使用除 -1 之外的其他超时来避免这种情况。

void start()

    if (_proc->state() == QProcess::NotRunning) 
    
        std::cout << "Starting process on node: " << _id << "\n";
        _proc->start(_args.at(0), _args.mid(1));
        if (_proc->state() == QProcess::Starting)
            _proc->waitForStarted(-1);
    

【讨论】:

我在连接后启动进程。 你能展示你的代码吗?您使用的是什么版本的 Qt? 哦,这是一个不错的解决方案。无论如何,我在 Qt bugtracker 上报告了一个错误/增强功能,因为避免一种看起来不自然的行为似乎有点不自然:我认为它不应该发生。无论如何,谢谢! 我同意,我的解决方案只是一种解决方法,不需要它。很高兴听到您将此情况报告给 Qt 错误跟踪器。

以上是关于QProcess readyRead before started的主要内容,如果未能解决你的问题,请参考以下文章

QProcess -> 在 Linux 上从 sftp 读取标准输出

使用QT的QProcess执行cmd命令记录

接收不到 QTcpSocket 的 readyRead 信号?

Qt的QTcpSocket ReadyRead信号的实现

QextSerialPort (QIODevice) 的 readyRead() 信号调用速度不够快

QTcpSocket readyRead() 信号多次发出