QNetworkReply readyRead signal and read&readAll function crashes in multi-threaded environment

78 views Asked by At

I tried to start the HTTP protocol in a thread to download a file, but I found that QNetworkReply calling the read or readAll method in a multithreaded environment would cause the program to crash. It can only write a few tens of MB of file each time, and then it crashes for no reason.

work.h

#ifndef WORK_H
#define WORK_H
#include <QFile>
#include <QNetworkAccessManager>
#include <QObject>
#include <QThread>
#include <QNetworkReply>
#include <QUrl>
#include <QEventLoop>

class Work:public QThread
{
    Q_OBJECT
public:
    Work(QString _fileName,QUrl _url,qint64 _offset, qint64 _end):fileName(_fileName),url(_url),
        offset(_offset),end(_end){ }

protected:
    void run () override;

private:
    QString fileName;
    QUrl url;
    qint64 offset;
    qint64 end;

    QNetworkAccessManager *manager;
    QNetworkReply *reply;
    QFile *file;
    QByteArray buf;
    QTime lastTime;
    qint64 lastByte=0;
};

#endif // WORK_H

work.cpp

#include "work.h"

#define KB 1024
#define MB KB*1024

void Work::run()
{
    Qt::HANDLE curId=QThread::currentThread();

    manager = new QNetworkAccessManager();
    reply = manager->get(QNetworkRequest(url));

    file=new QFile(fileName);
    if(!file->open(QIODevice::ReadWrite)){
        return;
    }

    file->seek(offset);

    //reply->setReadBufferSize(1024*2); //**Only set the access data to be less than 2Kb to avoid crashing; If the access data size is not set or set to greater than 2kb, it will also crash**
    connect(reply,&QNetworkReply::readyRead,this,[&](){
        while(reply->bytesAvailable()>0){
            buf = reply->readAll();
            //buf=reply->read(reply->bytesAvailable());   These two lines of code will crash if calling read() or readAll() function to read the buffer, On the contrary, once I try to annotate tow lines, it won't crash**
            file->write(buf);
        }
    });

    QObject::connect(reply, &QNetworkReply::downloadProgress, [&](qint64 bytesReceived, qint64 bytesTotal) {
        if (bytesTotal > 0) {
            int percentage = static_cast<int>((bytesReceived * 100) / bytesTotal);
           qDebug() << "Downloaded" << percentage << "%";
        }
    });

    QObject::connect(reply, &QNetworkReply::finished, [&]() {
        if (reply->error() == QNetworkReply::NoError) {
            qDebug() << "Download completed successfully!";
        } else {
            qDebug() << "Download failed:" << reply->errorString();
        }
        file->close();
        reply->deleteLater();
        manager->deleteLater();
        quit();
    });

    exec();
}

This is the debugging result:

enter image description here

0

There are 0 answers