创建 new
XMLHttpRequest
的实例并调用 send()
导致垃圾收集器无法清除的内存使用量,gc()
.调用delete
在对象上也不会清除内存。
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
Component.onCompleted: {
for(var i = 0; i < 100000; i++) {
console.log("Send request " + i)
var xhttp = new XMLHttpRequest
xhttp.open('get', 'someurl')
xhttp.send()
delete xhttp
}
gc() //why won't this clean the instances of XMLHttpRequest???
}
}
如果我从不打电话
xhttp.send()
那么我没有任何内存泄漏。由于没有对 var xhttp
的引用,因此开始进行垃圾收集。并且内存被释放。我想也许垃圾收集器没有触发,但是 gc()
也不会清除内存。这个 MRE 将运行 100,000 次迭代并在内存中保存大约 500MB。通过更改为
i < 1000000
可以轻松容纳 5.0GB .如何修复此内存泄漏并释放内存?
类似问题的引用:
QTBUG-43005 (No resolution)
QTBUG-50231 (No resolution)
现在记录在 QTBUG-83857
在这里,拥有 2.0GB 的内存。它保持了将近 4 个小时,直到我终止了该程序。当我关闭应用程序时,大约 60 秒后,整个 2GB 内存被释放
尝试使用 QNetworkAccessManager 类
//main.qml
MyClass {
id: myNetworkClass
Component.onCompleted: {
for(var i = 0; i < 10000; i++) {
myNetworkClass.doDownload()
}
}
}
//myclass.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QDebug>
class MyClass : public QObject
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = 0):QObject(){
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
}
public:
Q_INVOKABLE void doDownload() {
manager->get(QNetworkRequest(QUrl("https://esi.evetech.net/latest/characters/93610700")));
}
public slots:
void replyFinished(QNetworkReply *reply) {};
private:
QNetworkAccessManager *manager;
int count = 0;
};
#endif // MYCLASS_H
根据 htop 的说法,不幸的是,这也保留了内存并且不会释放它。
最佳答案
编辑
在 C++ 中创建一个新的控制类来处理您的 Web 请求,然后设置根上下文属性或在 QML 中注册类型并改用 C++ api。
这是最简单的方法:
在 myclass.cpp 中,您使用这种类型的代码以及适当的处理程序(replyFinished)创建一个方法
确保要从 QML 调用的方法在头文件中以 Q_INVOKABLE 为前缀(就在 void 之前)
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, &QNetworkAccessManager::finished,
this, &MyClass::replyFinished);
manager->get(QNetworkRequest(QUrl("http://qt-project.org")));
--
现在您只需注册类型并在 main.cpp 中创建一个实例
qmlRegisterType<MyClass>("MyClass", 1,0, "MyClass");
--
并在您的 QML 文件中执行
import MyClass 1.0
Window {
MyClass {
id: myNetworkClass
}
function doLookup() { myNetworkClass.myCustomMethod(); }
}
这将为您提供一种稳定的方法来避免由于在强类型框架上运行异步且弱类型的原生 javascript 环境而产生的 QML 问题......
祝你好运!
原创
首先,您通过创建请求而不保存对创建的对象的引用来留下挂起的对象引用......
将所有 XMLHttpRequest 对象的数组保存在 Window 的属性中
Window
{
property var requests: []
// ...
Timer {
onTriggered: {
// add request to array
requests.push(xhttp);
}
}
}
然后可能开始删除数组中的对象
...
var xhttp = requests.unshift()
xhttp.destroy()
但真正的问题是每隔 50 毫秒发送一次 http 请求
那是 ummm 每秒 20 个或 1200 个/分钟的请求
您可能需要调整代码以在前一个完成后发送请求..或将间隔设置为更高的值
关于javascript - QML 内存泄漏发送 XMLHttpRequest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61378389/