You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Qt多线程场景下实现将其他线程数据写入定时生成的TXT文件

解决方案:跨线程数据累计与每分钟批量写入文件

嘿,我来帮你搞定这个问题!你的核心需求是把TCP客户端线程每秒接收的数据累计起来,每分钟一次性写入对应时间命名的TXT文件里。目前文件是空的,问题出在你没有累计存储所有收到的数据,每次只写了最后一次覆盖的Data变量,而且没有建立数据的持续缓存机制。

核心解决思路

我们需要给每个客户端线程添加一个数据缓存容器,用来临时存储每分钟内收到的所有数据,等到QTimer触发写入时,再把缓存里的所有数据一次性写入文件,最后清空缓存准备下一轮数据收集。

修改后的代码实现

1. 更新mythread.h,添加数据缓存和线程安全锁

#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QObject>
#include <QTcpSocket>
#include <QThread>
#include <QDebug>
#include <QStringList>
#include <QMutex>

class MyThread : public QThread {
    Q_OBJECT
public:
    explicit MyThread(qintptr ID, QObject *parent = 0);
    void run();
signals:
    void error(QTcpSocket::SocketError socketerror);
    void sendValue(QString strValue);
    void close(QString disconnectId);
private slots:
    void readyRead();
    void disconnected();
    void InitThreadObjects();
    void sendData();
private:
    QTcpSocket *socket;
    qintptr socketDescriptor;
    QByteArray Data;
    QStringList dataBuffer; // 新增:存储每分钟的所有数据
    QMutex mutex; // 新增:确保缓存操作的线程安全
};
#endif // MYTHREAD_H

2. 修改mythread.cpp,实现数据累计与批量写入

#include "mythread.h"
#include <QThread>
#include <QTimer>
#include <QTime>
#include <QFile>
#include <QString>
#include <QTextStream>

MyThread::MyThread(qintptr ID, QObject *parent) : QThread(parent) {
    this->socketDescriptor = ID;
}

void MyThread::run() {
    qDebug() << " Thread started";
    socket = new QTcpSocket();
    if(!socket->setSocketDescriptor(this->socketDescriptor)) {
        emit error(socket->error());
        return;
    }
    connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection);
    connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected()));
    connect(this, &MyThread::started, this, &MyThread::InitThreadObjects);
    
    qDebug() << socketDescriptor << "Client connected";
    QString strValue = QString::number(socketDescriptor);
    emit sendValue(strValue);
    exec();
}

void MyThread::readyRead() {
    Data = socket->readAll();
    qDebug() << socketDescriptor << " Data in: " << Data;
    socket->write(Data);
    
    // 新增:将收到的数据加入缓存(加锁确保线程安全)
    QMutexLocker locker(&mutex);
    dataBuffer.append(Data);
}

void MyThread::disconnected() {
    qDebug() << socketDescriptor << " Disconnected";
    QString disconnectId = QString::number(socketDescriptor);
    emit close(disconnectId);
    socket->deleteLater();
    exit(0);
}

void MyThread::InitThreadObjects(){
    QTimer *timer = new QTimer(this);
    connect(timer,SIGNAL(timeout()),this,SLOT(sendData()));
    timer->start(60000);
}

void MyThread::sendData(){
    QTime currentTime = QTime::currentTime();
    QString time = currentTime.toString("hhmmss");
    QString filename = "/home/pi/"+time+".txt";
    qDebug() << filename;
    
    QFile file(filename);
    if(!file.open(QFile::WriteOnly | QFile::Text)) {
        qDebug() << "Could not open file for writing";
        return;
    }
    
    QTextStream out(&file);
    // 新增:批量写入所有缓存的数据
    QMutexLocker locker(&mutex);
    for(const QString& data : dataBuffer) {
        out << data << "\n"; // 每条数据换行,便于查看
    }
    // 清空缓存,准备下一分钟的数据收集
    dataBuffer.clear();
    
    file.flush();
    file.close();
}

关键修改点说明

  • 数据缓存容器:用QStringList dataBuffer来存储每分钟内收到的所有数据,避免每次收到新数据覆盖旧数据。
  • 线程安全锁:用QMutexQMutexLocker确保在多线程环境下(比如同时读写缓存)的操作安全,虽然这里每个客户端是独立线程,但加锁是良好的编程习惯。
  • 批量写入逻辑:在sendData中遍历缓存列表,把所有数据写入文件后清空缓存,确保下一分钟的数据不会和上一分钟混淆。

这样修改后,你的TCP客户端线程每秒收到的数据会被累计存储,每分钟QTimer触发时,就会把这一分钟内的所有数据一次性写入对应时间命名的TXT文件里啦!

内容的提问来源于stack exchange,提问作者김덕래

火山引擎 最新活动