0

QProcess waitForFinished() および waitForStarted() 呼び出しが機能する前に、次の Qt 4.8 コードに a.exec() 呼び出しを配置する必要がない理由を理解しようとしています。a.exec() がイベントループを開始することを理解しています。私の考えでは、waitFor* スロットは実行に移る前にシグナル (つまり 'started()' または 'finished()' ) を受信する必要があります。イベントループが開始されていない場合、これはどのように発生しますか?

waitForStarted() のドキュメント:

Blocks until the process has started and the started() signal has been emitted, or until msecs milliseconds have passed.

コード:

int main(int argc, char *argv[])
{

    QCoreApplication a(argc, argv);

    // Exec the i2c command to get the power button status
    QProcess i2cprocess;
    i2cprocess.start("/usr/bin/i2cget -f -y 1 0x4b 0x45");

    // Wait for it to start
    if(!i2cprocess.waitForStarted())
    {
        qDebug() << "Could not start QProcess to check power button status.";
        exit(-1);
    }

    // Wait for it to finish
    bool returnValue = i2cprocess.waitForFinished();
    if ( returnValue )
    {
        QByteArray status = i2cprocess.readAllStandardOutput().trimmed();
        bool ok;
        quint16 hexValue = status.toUInt(&ok, 16);
        qDebug() << "Power button status: " << status << hexValue << (hexValue & 0x01);

        // We want LSB
        exit(hexValue & 0x01);

    }
    else
    {
        qDebug() << "Error, process never completed to check power button status.";
        exit(-1);
    }

    return a.exec();

}
4

2 に答える 2

3

直接のシグナルスロット接続は単に間接的な関数呼び出しであり、イベント ループとは何の関係もありません。

ただし、waitForXxxxメソッドが行うことは、シグナルが発生するまでローカル イベント ループをスピンすることです。シグナルは、プロセスの状態が変化したことを OS から通知されるコードから発生します。そのコードは、機能的にはイベントループによって「実行されます」。

Qt では気まぐれに一時的なイベント ループを作成できることに注意してください。これは悪い習慣であり、waitForメソッドを使用するコードを書くべきではありません。通常は存在しない要件がコードに課せられるため、バグが発生します。

問題は、プロセスが状態を変更するのを待っているときに、イベント ループをどのように使用するかということです。内部的には、プロセス通知はネイティブ イベントまたはコールバックを待機する必要があり、それらはすべてイベント ループから処理されます。イベントが使用されていない場合でも、イベント ループは、OS がアプリケーションにコールバックを配信するために必要な割り込み可能なスリープを実行します。

于 2015-05-29T15:42:08.390 に答える
1

QProcessの Qt ドキュメントには次のように記載されています。

QProcess は、特定のシグナルが発行されるまで呼び出しスレッドを一時停止することにより、イベント ループなしで使用できるようにする一連の関数を提供します。

プロセスが開始されるまで、waitForStarted() はブロックします。

waitForReadyRead() は、現在の読み取りチャネルで新しいデータを読み取れるようになるまでブロックします。

waitForBytesWritten() は、データのペイロードが 1 つプロセスに書き込まれるまでブロックします。

waitForFinished() は、プロセスが完了するまでブロックします。

これらの関数をメイン スレッド (QApplication::exec() を呼び出すスレッド) から呼び出すと、ユーザー インターフェイスがフリーズする場合があります。

于 2015-05-28T12:50:44.083 に答える