1

私はQProcess初めて使用していますが、実験中にreadyRead以前に通知されていることに気付きましたstarted

で実行/usr/bin/echo foobarしてみました。とシグナルにQProcess2 つの関数を追加すると、次の順序で出力が得られます。readyRead()started()

  1. start()メソッドで処理開始
  2. dataReady() シグナル
  3. 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
4

1 に答える 1

2

最初にプロセスを開始してからシグナルを接続することで、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 バグ トラッカーに報告することをお勧めします。

編集:

あなたのコードで問題を再現できました。start()Nodeの機能を少し変更することで修正することもできました。続行する前に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);
    }
}
于 2013-04-28T20:22:37.663 に答える