6

公式ドキュメントに従って、私はこれをやろうとしています:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent)
{
    QThread *thread = new QThread;    
    Worker *worker= new Worker();

    worker->moveToThread(thread);

    //init connections

    thread->start();
}

ワーカー コンストラクター:

Worker::Worker(QObject *parent) :
    QObject(parent)
{
    serial = new QSerialPort(this);  //passing the parent, which should be the current thread      
}

コンパイル エラーはありませんが、実行すると次のようにスローされます。

QObject: Cannot create children for a parent that is in a different thread. 
(Parent is QSerialPort(0x11bd1148), parent's thread is QThread(0x11bd2ef8), current thread is QThread(0x3e47b8)

serialつまり、私が作成したスレッドではなく、メインスレッドを親として持っていることを教えてくれます。

コンストラクターでシリアルをインスタンス化せず、呼び出した後にトリガーされるメインプロセスで同じ結果になりますthread->start()

Worker::Worker(QObject *parent) :
    QObject(parent)
{             
}

Worker::doWork()
{
    if(!serial)
        serial= new QSerialPort(this); 

    //...
}

私は何が欠けていますか?


送信機能の例 (スロット):

void Worker::send(const QByteArray &data)
{
    serial->write(data);
    if( serial->waitForBytesWritten(TIMEOUT) )
        qDebug() << "sent: " << data;
}
4

1 に答える 1

8

要するに、このように QtSerialPort モジュールを使用するのは悪い考えです。

このモジュールは、GUI アプリケーションが QSerialPort クラスを使用するためのノンブロッキング メカニズムをすでに提供している QIODevice に基づいて設計されています。

次のシグナルを調べる必要があります。

void QIODevice::bytesWritten(qint64 バイト) [シグナル]

この信号は、データのペイロードがデバイスに書き込まれるたびに送信されます。bytes 引数は、このペイロードに書き込まれたバイト数に設定されます。bytesWritten() は再帰的に発行されません。イベント ループに再度入るか、bytesWritten() シグナルに接続されたスロット内で waitForBytesWritten() を呼び出すと、シグナルは再送信されません (ただし、waitForBytesWritten() は true を返す場合があります)。

と...

void QIODevice::readyRead() [シグナル]

このシグナルは、デバイスからの読み取りに新しいデータが使用可能になるたびに 1 回発行されます。ネットワークデータの新しいペイロードがネットワークソケットに到着したとき、またはデータの新しいブロックがデバイスに追加されたときなど、新しいデータが利用可能になったときにのみ再度送信されます。

readyRead() は再帰的に発行されません。イベント ループに再度入るか、readyRead() シグナルに接続されたスロット内で waitForReadyRead() を呼び出すと、シグナルは再送信されません (ただし、waitForReadyRead() は true を返す場合があります)。

QIODevice から派生したクラスを実装する開発者への注意: 新しいデータが到着したときは常に readyRead() を発行する必要があります (バッファにまだ読み取るデータがあるという理由だけで発行しないでください)。他の条件で readyRead() を発行しないでください。

ここにあるコマンドラインからこれを行うための2つの例を書きました。

コマンド ライン ライター非同期の例

コマンド ライン リーダーの同期の例

于 2014-05-09T16:35:12.353 に答える