当前位置: 首页 > article >正文

C++ QT 工具日志异步分批保存

C++ QT 工具软件一般可以如此实现日志保存:

#define THREAD_ID (reinterpret_cast<qulonglong>(QThread::currentThreadId()) & 0x0FFF)
#define TIME (QDateTime::currentDateTime().toString("yyyy_MM_dd_hh_mm_ss_zzz"))

#define LOGD(msg) qDebug()<<QString("[%1] [%2] [D] [%3] %4") \
.arg(TIME)\
.arg(THREAD_ID , 4) \
.arg(QString(TAG).mid(0,20) , 20 , QChar(' ')) \
.arg((msg));

当qDebug数据更新时,将日志更新到ui界面上,

存储日志时,将日志从ui界面导出,然后存储在本地

但是存在一个问题:

主线程中存储log可能会造成线程阻塞,界面失去响应

void ClassA::on_save_clicked()
{
    if (mFilePath.length() > 0)
    {
        QFile file(mFilePath);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text))
        {
            QTextStream stream(&file);
            stream << ui->plainTextEdit->toPlainText();
        }
        file.close();
    }
}

针对Qt中避免主线程卡死的问题,可以通过以下几种技术来避免:

  1. 使用多线程:将耗时的文件写入操作放在一个单独的线程中执行,这样可以避免阻塞主线程。在Qt中,可以使用QThread类来创建一个新线程,并在该线程中执行文件写入操作。这样可以确保主线程的响应性,不会因为长时间的文件操作而卡死。

  2. 异步编程:使用Qt的信号和槽机制,将文件写入操作异步化。您可以创建一个槽函数来处理文件写入,并在需要保存数据时发射一个信号,槽函数在接收到信号后异步执行文件写入操作。这样可以避免在主线程中同步执行耗时的文件操作。

  3. 使用TaskPool:如果您的应用是基于鸿蒙系统,可以使用系统自带的TaskPool多线程能力,将耗时任务交由子线程执行,避免主线程的长时间阻塞。

  4. 分批处理数据:类似于Linux的logcat技术,您可以将大量数据分批次写入文件,每次只处理一小部分数据,这样可以减少单次操作的时间,避免长时间的阻塞。

  5. 使用QCoreApplication::processEvents:在执行耗时操作时,偶尔调用QCoreApplication::processEvents()来处理所有挂起的事件,这样可以保持界面的响应性

eg1:

    void ClassA::on_save_clicked() {
        if (mFilePath.length() > 0) {
            QFile file(mFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream stream(&file);
                int batchSize = 1024 * 1024; 
                int totalDataSize = ui->plainTextEdit->toPlainText().length();
                int offset = 0;

                while (offset < totalDataSize) {
                    int chunkSize = qMin(batchSize, totalDataSize - offset);
                    QString chunk = ui->plainTextEdit->toPlainText().mid(offset, chunkSize);
                    stream << chunk;
                    offset += chunkSize;

                    // 处理完一批数据后,给主事件循环一些时间来处理其他事件
                    QCoreApplication::processEvents();

                    // 可以在这里添加一个简单的延时来控制写入速度,避免过于频繁
                    // QThread::msleep(10); // 例如,每次写入后暂停10毫秒
                }

                file.close();
            }
        }
    }

eg2:

void ClassA::on_save_clicked()
{
    if (mFilePath.length() > 0)
    {
        QtConcurrent::run([&]()
        {
            QFile file(mFilePath);
            if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QTextStream stream(&file);
                int batchSize = 1024 * 1024;
                int totalDataSize = ui->plainTextEdit->toPlainText().length();
                int offset = 0;
                while (offset < totalDataSize) {
                    int chunkSize = qMin(batchSize, totalDataSize - offset);
                    QString chunk = ui->plainTextEdit->toPlainText().mid(offset, chunkSize);
                    stream << chunk;
                    offset += chunkSize;
                }
                file.close();
            }
            emit logSaved();
        });
    }
}

更好的方法是在log server接收数据时保存

实时进行Log的临时保存,然后在需要保存的时候,将文件直接move到你想要保存的地方


http://www.kler.cn/a/392320.html

相关文章:

  • C++模板特化实战:在使用开源库boost::geometry::index::rtree时,用特化来让其支持自己的数据类型
  • 【专题】计算机网络之网络层
  • Nuxt 版本 2 和 版本 3 的区别
  • 利用阿里云下载 WebRTC 源码
  • Unity3D 包体裁剪与优化详解
  • 【秋招笔试-支持在线评测】11.13花子秋招(已改编)-三语言题解
  • 英伟达Isaac Manipulator产品体验
  • 【Vue3】知识汇总,附详细定义和源码详解,后续出微信小程序项目(3)
  • Error response from daemon:
  • OCRSpace申请free api流程
  • Power bi中的lookupvalue函数
  • Oracle In子句
  • 每日OJ题_牛客_春游_贪心+数学_C++_Java
  • Spark:背压机制
  • 南山前海13元一份的猪脚饭
  • mysql 几种启动和关闭mysql方法介绍
  • 青少年编程与数学 02-003 Go语言网络编程 18课题、Go语言Session编程
  • 大语言模型:解锁自然语言处理的无限可能
  • 鸿蒙UI开发——实现环形文字
  • 硬件---1电路设计安全要点以及欧姆定律
  • 【月之暗面kimi-注册/登录安全分析报告】
  • 如何在Puppeteer中实现表单自动填写与提交:问卷调查
  • k8s更新
  • 【Element】vue2 el-table scope.row 更改数据,试图没有更新
  • 《情商》提升:增强自我意识,学会与情绪共处
  • 请描述一下Spring Boot中的@SpringBootApplication注解的工作原理?