2009-06-10 30 views
5

私はコンソールベースのQCoreApplicationにタイマを持ち、ソケット通信を行いロックされたミューテックスを使用しています。QCoreApplicationを閉じる前にクリーンアップ

私は手動でアプリケーションを閉じると、それはいくつかのミューテックスがロックされ、それがタイムアウトしていると言ってエラーになります。ユーザーがコンソールアプリケーションを閉じるときに、コンソールアプリケーションでクリーンアップできる方法はありますか?

答えて

15

クリーンアップは、デストラクタと子と親の関係で処理する必要があります。

はQApplicationがある前に、それはすべてのチャイルズで破壊されるように、あなたのマスターオブジェクト(メインの1)はQApplicationの子を作成します。

スレッドをすべて削除してもよろしいですか?もしそうであればイベントループでスレッドを使用すると、あなたはまた、いくつかの特別なクリーンアップを行うには、ボイドQApplication::qAddPostRoutine (QtCleanUpFunction ptr) を使用することができますQThread::wait()

を呼び出す前に、イベントループを終了するQThread::quit()を呼び出してください。

それらのメッセージをデバッグするために、あなたはQtMsgHandler qInstallMsgHandler (QtMsgHandler h)を使用して、これらの警告をキャプチャするために、独自のメッセージハンドラを記述することができます。問題をシミュレートすることができれば、メッセージにブレークポイントを設定し、メッセージがどこから来ているかをスタック上で確認することができます。

void debugMessageHandler(QtMsgType type, const char *msg){ 
    if(QString(msg).contains("The message you can see in the console")){ 
     int breakPointOnThisLine(0);  
    } 

    switch (type) { 
     case QtDebugMsg: 
      fprintf(stderr, "Debug: %s\n", msg); 
      break; 
     case QtWarningMsg: 
      fprintf(stderr, "Warning: %s\n", msg); 
      break; 
     case QtFatalMsg: 
      fprintf(stderr, "Fatal: %s\n", msg); 
      abort(); 
    } 
} 

コンソールクローズシグナルをキャッチし、アプリケーションインスタンスにQCoreApplication::exit()を呼び出すことができデストラクタと親子関係船でクリーンアップするために。

#include <csignal> 
#include <QtCore/QCoreApplication> 
using namespace std; 

struct CleanExit{ 
    CleanExit() { 
     signal(SIGINT, &CleanExit::exitQt); 
     signal(SIGTERM, &CleanExit::exitQt); 
     signal(SIGBREAK, &CleanExit::exitQt) ; 
    } 

    static void exitQt(int sig) { 
     QCoreApplication::exit(0); 
    } 
}; 


int main(int argc, char *argv[]) 
{ 
    CleanExit cleanExit; 
    QCoreApplication a(argc, argv); 
    return a.exec(); 
} 
+0

がほぼ完成しました。exit(0)を呼び出すと、Qt固有のクリーンアップコードをシグナルハンドラexitQt()にないどこかで実行する必要があります。あなたのQtクリーンアップコードをaboutToQuit()シグナルに結びつけなければなりません。 aboutToQuitシグナルは、qApp-> exit(0)が呼び出されたときにだけ発行されます。 –

+2

C++ 11はより簡単になります: 'signal(SIGTERM、[](int sig){qApp-> quit();});' – ManuelSchneid3r

+0

これは完全には機能しません。クリーンアップ関連のオブジェクトをQApplicationの子にしました。デストラクタは、ウィンドウが正常に閉じられたときに適切に呼び出されます。しかし、システムのシャットダウン/ログアウト時には、QApplicationの子デストラクタは決して呼び出されません。 – galinette

1

あなたはQCoreApplication::aboutToQuit信号に接続し、そこに必要なクリーンアップを行うことができます。

+2

こんにちはダニエル、 私はこれを試してみましたが、ブレークポイントは、接続されたスロットにヒットしません。 QCoreApplicationで終了すると、aboutToQuitシグナルが出力されます。コンソールアプリケーションを閉じるとquit()が呼び出されますか? ありがとう、 Suresh。 –

5

は、「閉じる」(タイトルバーの赤いXボタン)を押して(win7の& VS2010で確認)を閉じるコマンドラインアプリケーションは、アプリケーションにSTATUS_CONTROL_C_EXIT信号を通過させることが判明しました。すべてのスレッドはこのコードで中止されます。

スレッドのメインスレッド '(0x980)は、コード-1073741510 (0xc000013a)で終了しました。

スレッド 'QThread'(0x2388)がコード -1073741510(0xc000013a)で終了しました。

これは、QCoreApplication::aboutToQuit()信号でこれを傍受する方法がないことを意味します。

winnt.hまたはntstatus.hを見てみましょう。これは マニフェスト定数STATUS_CONTROL_C_EXITに割り当てられた値です。ランタイムは、 のコードをプログラムで終了することを選択して、ユーザーのキャンセル の操作を記録します。

+0

SetConsoleCtrlHandler()を使用してこれらをインターセプトし、qApp-> exit(42)を呼び出して、 – Macke

関連する問題