2009-06-10 7 views
5

Ich habe eine Konsole-basierte QCoreApplication, die Timer hat und Socket-Kommunikation und verwendet auch gesperrte Mutex.Aufräumen vor dem Schließen der QCoreApplication

Wenn ich die Anwendung manuell schließe, gibt es einen Fehler, der besagt, dass ein Mutex gesperrt ist und das Zeitlimit überschritten wird. Gibt es eine Möglichkeit, in einer Konsolenanwendung aufzuräumen, wenn der Benutzer sie schließt?

Antwort

15

Bereinigung sollte von Destruktoren und Kind-Eltern-Beziehung behandelt werden.

Machen Sie Ihr Hauptobjekt (das Hauptobjekt) zu einem untergeordneten Objekt von QApplication, sodass es mit allen untergeordneten Objekten vor QApplication zerstört wird.

Sind Sie sicher, dass Sie alle Ihre Threads getötet haben? Wenn es einen Thread mit einer Ereignisschleife ist sicher QThread::quit() rufen Sie die Ereignisschleife zu beenden, bevor Sie QThread::wait() rufen

Sie können auch die Leere verwenden QApplication::qAddPostRoutine (QtCleanUpFunction ptr) einige spezielle Bereinigung zu tun.

Zum Debuggen dieser Nachrichten können Sie QtMsgHandler qInstallMsgHandler (QtMsgHandler h) verwenden und schreiben Sie Ihren eigenen Message-Handler, um diese Warnungen zu erfassen. Wenn Sie das Problem simulieren können, können Sie einen Haltepunkt für die Nachricht festlegen und auf dem Stapel sehen, von dem die Nachricht stammt.

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(); 
    } 
} 

Um mit destructor und Eltern-Kind-Beziehung Schiff zu säubern Sie die Konsole schließt Signal und QCoreApplication::exit() auf die Anwendungsinstanz anrufen zu fangen.

#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

fast abgeschlossen.Sobald Sie exit (0) aufgerufen haben, müssen Sie Ihren Qt-spezifischen Bereinigungscode irgendwo eingeben, der nicht im Signalhandler exitQt() enthalten ist. Also musst du deinen Qt Cleanup Code an das aboutToQuit() Signal binden. Das Signal aboutToQuit wird erst ausgegeben, wenn qApp-> exit (0) aufgerufen wird. –

+2

C++ 11 macht es einfacher: 'signal (SIGTERM, [] (int sig) {qApp-> quit();});' – ManuelSchneid3r

+0

Dies funktioniert nicht vollständig. Ich habe das Bereinigungsobjekt zu einem Kind von QApplication gemacht. Der Destruktor wird ordnungsgemäß aufgerufen, wenn das Fenster normal geschlossen wird. Beim Herunterfahren/Abmelden des Systems wird der untergeordnete Kinddestruktor QApplication jedoch nie aufgerufen. – galinette

1

können Sie mit QCoreApplication::aboutToQuit Signal verbinden und die notwendigen Aufräumarbeiten dort tun.

+2

Hallo Daniel, Ich habe dies versucht, aber Breakpoint nicht im angeschlossenen SLOT getroffen. Die Dokumentation sagt aboutToQuit Signal wird ausgegeben, wenn quit auf QCoreApplication aufgerufen wird. Ruft das Schließen der Konsolenanwendung quit() auf? Danke, Suresh. –

5

Stellt sich heraus, dass die Schließung Kommandozeilen-Anwendung (geprüft auf Win7 & VS2010) durch Drücken von ‚Schließen‘ (rote Taste auf x Titelleiste) übergibt das STATUS_CONTROL_C_EXIT Signal an die Anwendung. Alle Threads werden mit diesem Code abgebrochen.

Der Thread 'Haupt-Thread' (0x980) wird mit Code -1073741510 (0xc000013a) verlassen. Der Thread 'QThread' (0x2388) wurde mit dem Code -1073741510 (0xc000013a) beendet.

Das bedeutet, dass es keine Möglichkeit gibt, dies mit dem Signal QCoreApplication::aboutToQuit() abzufangen.

Werfen Sie einen Blick auf winnt.h oder ntstatus.h. Das ist der der manifeste Konstante STATUS_CONTROL_C_EXIT zugewiesene Wert. Die Laufzeit ist nur Wählen Sie, um Ihr Programm mit dem Code zu beenden, um die Operation des Benutzers zu notieren.

+0

Verwenden Sie SetConsoleCtrlHandler(), um diese abzufangen, und rufen Sie qApp-> exit (42) auf. – Macke

Verwandte Themen