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: