Qt5:如何使用qDebug()登录文件,多线程应用程序

时间:2015-04-04 17:14:56

标签: multithreading qt logging thread-safety

我几天前开始使用Qt5。我的应用需要一个记录器,我决定使用qDebug,但似乎必须重定向"为了将日志保存在文件中。

我使用qInstallMessageHandler来做这件事,我编写了自己的处理程序,如下所示(受到其他人的启发)。

它似乎有效,但由于我不是大师,我不得不问: 是否可以在多线程应用程序中使用它?

此外,如果在多线程应用程序中使用它是安全/安全的,可以以某种方式进行改进吗?

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

3 个答案:

答案 0 :(得分:3)

在Qt文档中找不到qDebug是线程安全的。因此,从多个线程同时调用它是不安全的,如果你不使用锁定机制,你会遇到混合输出。

如果你使用QMutexLocker,你的锁定方法会更好,因为Qt文档强烈建议:

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

第二种方法是提供具有用于写入日志的槽的工作者类。然后,您可以在新线程中拥有它的实例,并使用QMetaObject::invokeMethod连接类型Qt::QueuedConnection在消息处理程序中调用它的插槽。这样,来自每个线程的每个调用都将排队并在工作线程中进行处理,因为所有工作都在一个单独的线程中完成,所以它可能会有更好的性能。

答案 1 :(得分:2)

您的方法看起来简单干净。我保持这样。

您可以改进一件事:在应用程序启动时只打开一次文件,关闭应用程序时关闭它。打开文件是一项昂贵的操作。

您可以从多个线程写入相同的打开文件,因为您的互斥锁确保只有一个线程同时写入。

答案 2 :(得分:0)

我没有收到关于您对呆滞现象的担忧的回复,我敢肯定,这次您已经找到了答案。您可以通过减少关键区域内的代码量来提高性能。文件操作很慢,因此请尝试减少花费的时间。这可以包括保持文件打开状态,缓冲日志并定期写入,在锁定区域之外构造条目以及

void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{

    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));
    QString entryString("%1 %2: %3");
    entryString = entryString.arg(timeStr).arg(contextString).arg(msg);

    QFile outFile("file.log");

    mutex.lock();
    outFile.open(QIODevice::WriteOnly | QIODevice::Append);  
    QTextStream stream(&outFile);  
    stream << entryString << endl;    
    mutex.unlock();
}