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

סטנ*_*ונן 11 logging qt multithreading 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();
}
Run Code Online (Sandbox Code Playgroud)

Nej*_*jat 5

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

如果您使用QMutexLockerQt 文档强烈推荐的锁定方法,则您的锁定方法会更好:

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

第二种方法是提供一个工作类,该类具有用于写入日志的插槽。那么你可以有它的一个实例在一个新的线程,并使用调用它的插槽,消息处理QMetaObject::invokeMethodQt::QueuedConnection连接类型。这样,来自每个线程的每个调用都将在工作线程中排队和处理,并且它可能具有更好的性能,因为所有工作都在单独的线程中完成。


Sim*_*rta 4

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

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

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