1

2D プロット ライブラリである xmgrace へのカスタム コントロール インターフェイスを開発するために Qt を使用しています。私のプロジェクトには 3 つのコンポーネントがあります。

  1. Qtで作られたGUI
  2. バックグラウンド スレッドで C からいくつかの共有オブジェクト コードを実行する QThread。
  3. パイプを使用して上記の両方に接続された xmgrace ウィンドウ。(grace_np ライブラリを使用)

からの通信(1) --> (2)は、共有オブジェクト コードで宣言されたいくつかのグローバル変数のステータスを変更することによって行われます。

(1) --> (3)&からの通信(2) --> (3)は、grace_np ライブラリによって提供される組み込み関数を使用しています。

今、(2) --> (1)問題を引き起こしているのは からの通信です。考えられる2つの方法を試しました:a)Qtシグナルを発行し、Cコード内で呼び出されるQtコードで共有オブジェクトを宣言します。b) スレッドから戻り、戻り値を使用して何らかの操作を実行してから、スレッドを再起動します。

これらの方法論はどちらも信頼できない結果をもたらしました。GUI が動かなくなったり、セグメンテーション エラーが発生したりして、次のメッセージが表示されます。

QProcess: Destroyed while process is still running

コードのどこにも QProcess クラスを使用していません。だからこれは謎になった。これについて考えられる原因について、いくつかの情報を提供してください。

PS: へのパイプ(3)は一方向であり、その方向のみが必要です。

編集1:

参考までに、私は Qt 4.2 を使用しているため、QObject アプローチを使用してから movetothread() を使用することはできません。会社のポリシーのためにコードを配置できず、コードを配置していないため、申し訳ありません。何を入れるかを知っています(大きすぎます)。共有の C コードは 40 万行以上

私は自分の問題の犯人を見つけたと信じています。クラス QMessageBox を使用すると、この問題が発生するようです。最初は QMessageBox の静的関数を使用していました。スタックとヒープの両方で宣言しようとしましたが、問題は解決しません。しかし、コードから QMessageBox へのすべての呼び出しを削除すると、問題が解決することがわかりました。しかし、問題は、メッセージを表示するにはどうすればよいかということです。私はここで推測していますが、QMessageBox のモーダルな性質が私のプログラムと xmgrace の間に存在するパイプをブロックし、その後終了させる可能性はありますか? 次に、カスタム QMessageBox (非モーダル) を作成すると、この問題が解決する場合があります。

編集2:

ワーカー スレッドから QMessageBox を呼び出しているわけではありません。さらに、ワーカー スレッドを使用している方法では、プログラムを閉じない限り戻りません。アイデアを与えるために、私の QThread::run 関数は次の形式です。

QThread_Object::run()
{
  c_init();
  c_main();
}

ここで、c_init と c_run は共有 C コードからリンクされた関数です。そのため、これらの中から QMessageBox を直接呼び出すことはできません。今のところ、QMessageBox を廃止し、代わりに QMainWindow ステータス バーを使用する予定です。しかし、それではすべての機能が提供されるわけではありません。これはQt 4.2のバグである可能性があると思います

編集3:

からの通信(2) --> (1)が問題の原因であると前述しました。今、私はこの通信を完全に廃止し、ワーカー スレッドの開始後にいつでも QMessageBox を呼び出すことによって問題が発生することをより正確に発見しました。上記の通信により、Qt が間接的にシグナルを送信し、QMessageBox を呼び出していましたが、これが原因であると私は信じています。

編集4:

わかりました、最初からこの問題を取り巻く最大の謎について言及するのを忘れていました。私は基本的に、このプログラムをコーディングして実行するワークステーション(Place B)でssh経由で作業(Place A)します。B は 2 つの物理ネットワークに接続されています。A はネットワーク 1 を介して B に接続されています。現在、A の端末から作業している間 (つまり、ネットワーク 1 経由の ssh)、この問題は発生していません。ただし、B に直接アクセスするか、ネットワーク 2 経由で ssh を介してアクセスすると、一貫して発生します。コードが B でのみ実行されるたびに注意してください。これらのネットワークは両方とも百人隊長によって使用されています。

編集 5

最後に、QMessageBox の拡張機能を実際には必要としないため、QDialog をサブクラス化し、カスタム MessageBox を作成することで問題を解決しました。QMessageBox 内で正確に何が問題を引き起こしているのか、まだわかりません。常に謎のままであるQt内のバグを推測します。

4

1 に答える 1

1

ここには少し暗闇の中で撮影しているコードがないため、意図的かどうかにかかわらず、QProcessがスタック上に作成されたか、QThreadが途中で破棄されているようです。正しく起動されていないQThreadオブジェクトにお金をかけます。ドキュメントは(または最近まで)厄介なので、あなたを責めるのは難しいです。このスレッドこのスレッドを読むことを検討してください。QThreadをサブクラス化しないでください。

編集: QMessageBoxが原因である場合は、子スレッドから表示していると思います。ドキュメントから:

GUIアプリケーションでは、メインスレッドはGUI関連の操作を実行できる唯一のスレッドであるため、GUIスレッドとも呼ばれます。

子スレッドからのメッセージを表示する方法はいくつかあります。個人的には、qtのエラー報告スキームを使用して、qCritical、qDebugなどをにリダイレクトしstderrます。これを行うもう1つの簡単な方法はemit、GUIスレッドによってキャッチされたワーカースレッドからのQStringシグナルを取得することです。これにより、エラーが表示/収集されます。MainWindowにエラーを収集させ、ワーカースレッドが終了したときにそれらをすべて一度に表示するのが好きです。

編集2: 問題はQMessageBoxがモーダルである(つまり、ワーカースレッドが前進している間にメインスレッドをブロックする)ことであると思われるため、QMessageBoxを非モーダルモードで使用することでこれを簡単に解決できます。0QMessageBoxコンストラクター/静的関数で親ウィジェットとして渡すだけです。ユーザーがウィンドウを終了するのを待たずに処理が続行されます。これにより、複数のメッセージボックスが同時に開かれる可能性もあります。それがエラーを回避するのに役立つ場合は、コードを注意深く調べて、閉じた後にウィンドウが適切に破棄されることを確認してください。

于 2013-02-21T17:32:38.403 に答える