2015-04-04 2 views
8

Ich begann mit Qt5 vor ein paar Tagen. Ich brauchte einen Logger für meine App und ich entschied mich, qDebug zu verwenden, aber es scheint, dass es "umgeleitet" werden muss, um die Protokolle in einer Datei zu haben.Qt5: So verwenden Sie qDebug(), um eine Datei, Multi-Thread-Anwendung einzuloggen

Ich benutzte qInstallMessageHandler, um das zu tun, und ich schrieb meine eigene Handler wie unten dargestellt (inspiriert von anderen Menschen hier).

Es scheint, es funktioniert, aber da ich kein Guru bin, muss ich fragen: Ist es in Ordnung, dies in einer Multithread-Anwendung zu verwenden oder nicht?

Auch, wenn es in einer Multithread App in Ordnung/sicher ist, kann es irgendwie verbessert werden?
Danke!

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) 
{ 
    mutex.lock(); 

    QDateTime dateTime(QDateTime::currentDateTime()); 

    QString timeStr(dateTime.toString("dd-MM-yyyy HH:mm:ss:zzz")); 
    QString contextString(QString("(%1, %2)").arg(context.file).arg(context.line)); 

    QFile outFile("file.log"); 
    outFile.open(QIODevice::WriteOnly | QIODevice::Append); 

    QTextStream stream(&outFile); 
    stream << timeStr << " " << contextString << ": " << msg << endl; 

    mutex.unlock(); 
} 
+0

Welcher Typ hat Ihre Variable 'Mutex'? –

+0

statischer QMutex Mutex; // globale Variable –

+0

Für welches Betriebssystem entwickeln Sie? –

Antwort

1

Ihr Ansatz sieht einfach und sauber aus. Ich würde es so halten.

Es gibt eine Sache, die Sie verbessern können: Öffnen Sie die Datei nur einmal beim Start der Anwendung und schließen Sie sie beim Schließen der Anwendung. Das Öffnen einer Datei ist eine teure Operation.

Sie können aus mehreren Threads in die gleiche offene Datei schreiben, da Ihr Mutex sicherstellt, dass nur ein Thread gleichzeitig schreibt.

+0

Simon, danke, dass du dir die Zeit genommen und dich beraten hast! Ich würde die Datei nur einmal beim Start öffnen, aber (in naher Zukunft) plane ich, den Dateinamen von "file.log" zu etwas wie "TT-MM-yyy.log" zu ändern ... Ich bin Sicher weißt du was ich meine :) Es wäre also irgendwie unmöglich die Log-Datei beim Programmstart zu öffnen ... Irgendeine Idee/Workaround für dieses Problem? Danke im Voraus! –

+0

@groenhen Erwarten Sie, dass die Anwendung mehr als einen Tag läuft? –

+0

Ja, es wird nonstop laufen (zumindest hoffe ich das:) ...) –

2

Sie können nicht überall in der Qt-Dokumentation finden, dass qDebug Thread-sicher ist. Es ist also nicht sicher, es gleichzeitig aus mehreren Threads aufzurufen, und Sie würden in der Tat eine gemischte Ausgabe erhalten, wenn Sie keinen Sperrmechanismus verwenden.

Ihr Verriegelungs Ansatz wäre besser, wenn Sie QMutexLocker verwenden, da es stark von der Qt-Dokumentation empfohlen:

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg) 
{ 
    QMutexLocker locker(&mutex); 
    ... 
} 

Ein zweiter Ansatz ist es, eine Arbeiter-Klasse zu schaffen, das Schlitze für das Schreiben des Protokolls hat. Sie können dann eine Instanz davon in einem neuen Thread haben und sie im Message-Handler unter Verwendung von QMetaObject::invokeMethod mit einem Qt::QueuedConnection Verbindungstyp aufrufen. Auf diese Weise würde jeder Aufruf von jedem Thread in den Worker-Thread eingereiht und verarbeitet werden, und er hätte wahrscheinlich eine bessere Leistung, da der gesamte Job in einem separaten Thread ausgeführt wird.

+1

Aber AFAIK, "QMutexLocker Schließfach (& Mutex);" macht den gleichen Job wie mutex.lock(), gefolgt von mutex.unlock(), der einzige Unterschied ist, dass Sie sich keine Sorgen machen müssen, wenn/wenn diese Funktion/Methode mehrere Exit/Return-Punkte hat. Der Mutex wird beim Verlassen automatisch entsperrt, da das Schließfach eine automatische Variable ist. Grüße, SG. –

+0

BTW: Was ist mit "in Bezug auf die Geschwindigkeit" ...? Welche führt schneller, Mutex Lock/Unlock() oder ein QMutexLocker-Mechanismus? –

+0

Ich bin mir nicht bewusst, ob sie sich in der Geschwindigkeit unterscheiden. Ein zweiter Ansatz besteht darin, einen Worker-Thread zu verwenden und dort Operationen auszuführen. Siehe die bearbeitete Antwort. – Nejat

Verwandte Themen