8

私の質問のタイトルが正しく定式化されているかどうかわからないので、私が本当に意味することを説明するために、次の例を考えてみましょう:

と を作成し、QApplicationそのQWidget上に を作成QPushButtonします。次に、次のようなボタンからのクリック シグナルにハンドラーをアタッチします。

void MyWidget::on_pushButton_clicked(){
    //Never return
    while(true);
}

最後に、アプリケーションのイベント ループを開始し、プログラムを実行してウィンドウが表示されたら、ボタンをクリックします。

私の場合、これはアプリケーション全体を停止させます。この時点での私の質問は、この種のハングアップがコードからアプリケーションで発生したことをどのように「検出」できるかということです。

シグナルハンドラーで返されないコードを書くのは悪い習慣であることは知っています。エラーを検出してエラーから回復したいので、この質問をします。本番環境での回復力を向上させるために、アプリケーションを完全に再起動する可能性があります。

ありがとう!

4

2 に答える 2

7

いくつかのアイデア、実際の解決策は、何をする必要があるか、どのようなフィードバックが必要かによって異なります (UI のポップアップ、ログに記録されたもの、デバッグ機能など)。

QTimer を使用して、自分のスロットの呼び出し間の時間を記録します

予想されるタイマー タイムアウトよりも大幅にスロットの呼び出しが遅れる場合は、イベント ループがどこかでスタックしています。これにより、問題が発生したことがわかりますが、どこでスタックしたかはわかりません。

別の QThread を使用する

メインスレッドに存在するオブジェクトに定期的にシグナルを送信します(またはイベントを送信します。クロススレッドシグナルはイベントを介して実装されます)。そのシグナルに接続されたスロットは、シグナルをスレッドに送り返します。「pong」に時間がかかりすぎる場合 (スレッドに別のタイマーを設定できます)、何かを実行します -- abort()raise()つまり、デバッガーを停止させ、メインのスレッド スタック トレースを表示して、どこに到達したかを推測するアクションを実行します。立ち往生。

別のスレッドを実行しているため、メッセージボックスなどをポップアップすることはできないことに注意してください。他のスレッドには UI はありません! せいぜい、イベントをログに記録します。

別のスレッドを使用する (2)

Qt のイベント ループはいくつかのシグナルを発行します (QAbstractEventLoop を参照)。理論的には、別のスレッドでそれらにアタッチし、制御がそれ以上戻っていないかどうかを検出できます。または、QAEL を同じ手段にサブクラス化します。

QTcpServer / QLocalServer を使用する

ping/pong の概念は同じですが、別のプロセスを使用します -- pong が短時間で返されない場合にアプリケーションに定期的に ping を送信する小さな TCP / ローカル ソケット クライアントを記述します (UI を使用することもできます)。 )。

于 2014-08-01T09:40:14.117 に答える