11

QtSerialPortライブラリを使用して、USB 経由で仮想 COM ポートと通信しています。COM ポートはデータを返し、QtSerialPort で指定されたサンプル プロジェクトでテストすると正しく動作しますが、プロジェクトの一部として実行すると失敗します。

QtSerialPort がインスタンス化されるまでのインスタンス化チェーンとスレッドを調べたところ、少し奇妙なことがわかりました。結果は以下のとおりです。

main()
  MainWindow (Thread 0xbf8dbe0)        // Thread "A"
    HardwareManager (Thread 0xbf8dbe0) // Thread "A"
      QSerialPort (Thread 0xbfb95f0)   // Thread "B" !?

私のコードでは、main() 関数が MainWindow をインスタンス化し、次にそれが HardwareManager をインスタンス化し、それをプライベート変数として格納します。HardwareManager がインスタンス化されると、QSerialPort インスタンスもインスタンス化されるため、COM ポートと適切に通信できます。

ただし、上記のように、私の QSerialPort は親オブジェクトとは別のスレッドにあり、親オブジェクトでもあります (両方の祖先がスレッド A にあるのに対し、スレッド B にあります)。この他のスレッドが私のシグナル/スロットの失敗を引き起こしていると思います。dumpObjectInfoを実行すると、Signal/Slot が設定されていると表示されますが、イベントは発生しません。

this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData());

上記は、新しいシリアル ポートを作成して適切なスロットに接続するために使用するコードです。実際のボー、パリティ、およびデータ/ストップ ビットの構成は個別に行われます (QtSerialPort が提供するサンプル アプリでテストされているように、正しく動作します)。

この特定のオブジェクト (QSerialPort インスタンス) が別のスレッドでインスタンス化されている理由について、誰かが洞察を持っていますか? スレッドの関連付けを切り替えるために「moveToThread」を試しましたが、何も機能していないようです。

Qt Project Forumsにも投稿しましたが、有用な回答はまだありません。

編集: 以下は、コール チェーン内の関連するコードです。

// main()
QApplication a(argc, argv)
MainWindow window = new MainWindow(); // [1]
MainWindow.show();
return a.exec();

// MainWindow::MainWindow() [1]
this->toolController = new QtToolController(this);
HardwareManager *manager = new HardwareManager(this->toolController); // [2]

// HardwareManager::HardwareManager() [2]
this->serial = new QSerialPort();
connect(this->serial, SIGNAL(readyRead()), this, SLOT(readSerialData()));

QSerialPort から読み取る準備ができると (提供するデータがある場合)、readyReadシグナルを発します (少なくとも、発火するはずです)。このシグナルは Qt のサンプル プロジェクトでは正しく発火しますが、私のアプリケーションではシグナルを受け取りません。シグナルが届かないのは、これらのスレッドの問題が原因だと思います。

4

2 に答える 2

2

別のスレッドからのシグナルをキャッチするためにQueuedConnectionを使用できます。

connect(this->serial, SIGNAL(readyRead()), 
    this, SLOT(readSerialData()), Qt::QueuedConnection);

このように、コントロールがイベント ループに戻ったら、メイン スレッドのコンテキストでスロットを実行する必要があります。

また、この投稿は、QtSerialPort の親を設定するべきではないことを示唆しているようです (おそらく moveToThread が親を持つ QObjects で機能しないため)。

于 2013-03-05T12:56:48.820 に答える
1

この問題に遭遇した他の人が回答を利用できるようにするという精神で、この問題はリリース/デバッグ ビルドに関連していました。QtSerialPort ライブラリはリリース環境専用に構築されていましたが、何らかの理由でアプリケーションをデバッグ モードで実行するとリリース QtSerialPort にリンクし、スレッド コンテキストが失われました。

これを修正するために、適切なバージョンのライブラリをビルドしたことを確認し、自分の環境に適したバージョンにリンクしたことを確認しました。

于 2014-03-10T20:22:38.287 に答える