簡體   English   中英

QML Memory 泄漏發送 XMLHttpRequest

[英]QML Memory leak sending XMLHttpRequest

創建XMLHttpRequestnew實例並調用send()會導致垃圾收集器無法清除 memory 的使用,也無法清除gc() 在 object 上調用delete也不會清除 memory。

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()那么我沒有任何 memory 泄漏。 垃圾收集開始了,因為沒有引用var xhttp並且 memory 被釋放。 我想也許垃圾收集器沒有觸發,但gc()也不會清除 memory 。

這個 MRE 將運行 100,000 次迭代,並在 memory 中保存大約 500MB。 這可以通過更改為i < 1000000輕松容納 5.0GB。

如何修復此 memory 泄漏並釋放 memory?

類似問題的參考: QTBUG-43005(無解析) QTBUG-50231(無解析)

現在記錄在QTBUG-83857

在此處輸入圖像描述 在這里,持有 2.0GB 的 memory。 它保持了將近 4 個小時,直到我終止了該程序。 當我關閉應用程序時,大約 60 秒后,整個 2GB memory 被釋放

嘗試使用 QNetworkAccessManager class

//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 的說法,不幸的是,這也保留了 memory 並且沒有釋放它。

編輯

Create a new controlling class in C++ to handle your web requests and then set a root context property or register the type in QML and use the C++ api instead.

這是 go 的最簡單方法:

在 myclass.cpp 中,您使用這種類型的代碼以及適當的處理程序(replyFinished)創建一個方法

確保要從 QML 調用的方法在 header 文件中以 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 問題,該環境在強類型框架上是異步且弱類型的...

祝你好運!

原來的

首先,通過創建請求而不保存對創建的 object 的引用,您將掛起 object 引用...

在 Window 的屬性中保留所有 XMLHttpRequest 對象的數組

Window
{
    property var requests: []
// ...

    Timer {
       onTriggered: { 
 //  add request to array
             requests.push(xhttp);
       }
    }
}

然后也許開始刪除數組中的對象......

var xhttp = requests.unshift() 
xhttp.destroy()

但真正的問題是每隔 50 毫秒發送 http 請求

那是 ummm 每秒 20 個或 1200 個/分鍾的請求

您可能需要調整代碼以在前一個完成后發送請求..或將間隔設置為更高的值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM