2016-06-24 9 views
0

Ich verwende qInstallMessageHandler, um eine benutzerdefinierte Protokollierungsfunktion zu registrieren. Diese Funktion formatiert die Nachricht (z. B. fügt sie einen Zeitstempel hinzu) und gibt sie an die Konsole und an die Protokolldatei aus.Können Qt-Bibliothekskomponenten qDebug() oder ähnlich aufrufen?

Meine Sorge ist, wenn die Qt-Bibliothek Komponenten (wie QDateTime, QDir, QFile ...) qDebug() nennen kann, qWarning() usw.?

Wenn ja, dies auf die unendliche Rekursion führen kann ...

+3

Ja, Qt selbst verwendet diese Debug/Warnfunktionen, Sie müssen sich also selbst schützen. – peppe

Antwort

1

Die einfache Antwort ist: Vermeiden Sie Ihre Nachricht Handler reentering, dann:

// C++11, Qt 5.4+ 
void myMessageHandler(…) { 
    thread_local bool entered = false; 
    if (entered) return; // oops 
    QScopedValueRollback set{entered, true}; 
    … 
} 

// C++11, Qt 4.8+ 
void myMessageHandler(…) { 
    thread_local bool entered = false; 
    if (entered) return; // oops 
    QScopedValueRollback back{entered}; 
    entered = true; 
    … 
} 

// C++98, Qt 4 
QThreadStorage<bool> entered; 
void myMessageHandler(…) { 
    if (entered.localData()) return; 
    QScopedValueRollback back(entered.localData()); 
    entered.localData() = true; 
    … 
} 

Das war die alte und dumme Antwort, denn Nachwelt:

Es führt zu unendlicher Rekursion nur, wenn Ihre Protokollierung synchron ist. Sobald Sie die Protokollierung asynchron vornehmen, erhalten Sie das Problem nicht mehr: Der Message-Handler wird nicht mehr neu eingegeben, da Sie ihn sofort nach dem Aussenden eines Signals verlassen, und die Signalemission über eine in der Warteschlange stehende Verbindung wird mit Null oder Null gesendet mehr QMetaCallEvent Instanzen zu den Ereigniswarteschlangen relevanter Threads und das ist es.

Asynchrone Protokollierung wird erreicht, indem ein Signal im Message-Handler ausgegeben wird und das Protokollschreiben von einem Slot/Funktor gehandhabt wird, der über eine explizit eingereihte Verbindung mit dem Signal verbunden ist. Wahrscheinlich möchten Sie, dass sich Ihr Logger in einem eigenen Thread befindet. Das ist also ein sehr natürlicher Ansatz und funktioniert hervorragend.

+0

nette Idee! Danke. Welches Objekt sollte dieses Signal abgeben? Kannst du bitte ein Beispiel geben? – user2449761

+0

@ user2449761 Ein Objekt speziell für den Zweck, natürlich gemacht. Ein Hilfsobjekt, wenn Sie so wollen. Es kann ein globaler Singleton sein, der in 'main()' zugewiesen wird, bevor die Anwendungsinstanz erstellt wird. –

+0

Das asynchrone Protokollierungsobjekt erstellt keine Rekursion, sondern eine unendlich wachsende Ereigniswarteschlange. Dies ist noch schwieriger zu erkennen – user2449761

Verwandte Themen