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

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.lryc.cn/news/482860.html

相关文章:

  • win32com库基于wps对Word文档的基础操作
  • Kubernetes 网络之深度探索:网络模型与 CNI 插件
  • Go 模块管理教程:go.mod 与依赖版本控制
  • 大数据 ETL + Flume 数据清洗 — 详细教程及实例(附常见问题及解决方案)
  • 鸿蒙next版开发:订阅应用事件(ArkTS)
  • F litter 开发之flutter_local_notifications
  • springboot参数校验
  • Spring生态学习路径与源码深度探讨
  • C++:set详解
  • (一)- DRM架构
  • Docker了解
  • 【DL】YOLO11 OBB目标检测 | 模型训练 | 推理
  • vue读取本地excel文件并渲染到列表页面
  • github 以及 huggingface下载模型和数据
  • 使用 Vue 配合豆包MarsCode 实现“小恐龙酷跑“小游戏
  • 51c视觉~合集6
  • STM32(hal库)在串口中,USART和uart有什么区别?
  • 机器学习、深度学习面试知识点汇总
  • FPGA高速设计之Aurora64B/66B的应用与不足的修正
  • 如何通过PHP脚本自动推送WordPress文章至百度站长平台
  • ORA-01092 ORA-14695 ORA-38301
  • upload-labs通关练习---更新到15关
  • WPF 应用程序中使用 Prism 框架时,有多种方式可以注册服务和依赖项
  • 【ESP32】ESP-IDF开发 | 低功耗管理+RTC唤醒和按键唤醒例程
  • Windows 局域网IP扫描工具:IPScaner 轻量免安装
  • HTML的浮动与定位
  • 【网络安全 | 漏洞挖掘】我如何通过路径遍历实现账户接管
  • DB-GPT系列(四):DB-GPT六大基础应用场景part1
  • SpringCloud篇(服务拆分 / 远程调用 - 入门案例)
  • Rust 建造者模式