סטנ*_*ונן 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)
在 Qt 文档中找不到qDebug线程安全的任何地方。因此,从多个线程同时调用它是不安全的,如果不使用锁定机制,确实会遇到混合输出。
如果您使用QMutexLockerQt 文档强烈推荐的锁定方法,则您的锁定方法会更好:
void MessageHandler(QtMsgType type, const QMessageLogContext & context, const QString & msg)
{
QMutexLocker locker(&mutex);
...
}
Run Code Online (Sandbox Code Playgroud)
第二种方法是提供一个工作类,该类具有用于写入日志的插槽。那么你可以有它的一个实例在一个新的线程,并使用调用它的插槽,消息处理QMetaObject::invokeMethod与Qt::QueuedConnection连接类型。这样,来自每个线程的每个调用都将在工作线程中排队和处理,并且它可能具有更好的性能,因为所有工作都在单独的线程中完成。
你的方法看起来简单干净。我会保持这样。
您可以改进一件事:仅在应用程序启动时打开文件一次,并在关闭应用程序时将其关闭。打开文件是一项昂贵的操作。
您可以从多个线程写入同一个打开的文件,因为互斥体确保只有一个线程同时写入。