2016-05-10 6 views
0

Ich entwickle eine Anwendung, die Anforderungen an einen Server sendet, der QtNetworkAccessManager verwendet, und speichert die Antworten. Ich habe es geschafft, aber die Speicherbelegung steigt stetig an und blockiert den ganzen PC. Ich denke, das Problem hängt mit dem Aufruf von deleterater() und der Ereignisschleife zusammen, aber ich kann nicht sehen, wie ich es beheben kann. Hier ist der Code:QNetworkAccessManager Speicherprobleme

main.cpp

int main(int argc, char *argv[]) 
{ 
    QCoreApplication a(argc, argv); 
    ReadConfig(); 
    Ethernet M2; 
    return a.exec(); 
} 

Ethernet.h

class Ethernet : public QObject 
{ 
    Q_OBJECT 

public: 
    Ethernet(); 
    ~Ethernet(); 
    QTimer *timer; 

private 
    QNetworkAccessManager *manager; 

public slots: 
    void Cycle(); 
    void replyAuthenticationRequired(QNetworkReply *reply, QAuthenticator *auth); 
    void replyFinished(QNetworkReply *reply); 
}; 

Ethernet.cpp

Ethernet::Ethernet() 
{ 
    timer = new QTimer(this); 
    connect(timer, SIGNAL(timeout()), this, SLOT(Cycle())); 
    timer->start(1000); 

    manager = new QNetworkAccessManager(this); 
    connect(manager, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), this, SLOT(replyAuthenticationRequired(QNetworkReply*,QAuthenticator*))); 
    connect(manager, SIGNAL(finished(QNetworkReply*)), this,  SLOT(replyFinished(QNetworkReply*))); 
} 

void Ethernet::Cycle() 
{ 
    for (BYTE i=0; i< NUM_TOTAL_VEHICLES; i++) 
    { 
     FailCheck(i,FILTER_VALUE_PRIORITY_A1); 
     FailCheck(i,FILTER_VALUE_PRIORITY_A); 
     FailCheck(i,FILTER_VALUE_PRIORITY_B); 
     FailCheck(i,FILTER_VALUE_PRIORITY_C); 
    } 
} 

void Ethernet::FailCheck (BYTE coach, BYTE priority) 
{ 
    //Build a valid URL 
    QString qsURL = "http://"; 
    ... 
    .. 
    . 
    // 

    manager->get(QNetworkRequest(QUrl(qsURL))); 
} 

void Ethernet::replyAuthenticationRequired(QNetworkReply *reply, QAuthenticator *auth) 
{ 
    if(!reply->error()) 
    { 
     auth->setUser(DB_USR); 
     auth->setPassword(DB_PWD); 
    } 
    reply->deleteLater(); 
} 

void Ethernet::replyFinished (QNetworkReply *reply) 
{ 
    if(!reply->error()) 
    { 
     //Do some task with the reply; 
    } 
    reply->deleteLater(); 
} 

ich irgendwelche Vorschläge zu schätzen wissen. Vielen Dank!

+0

Sie haben keine Ereignisschleife in Ihrer Ethernet-Klasse, also deleteLater - funktioniert nicht – tty6

+0

Der von Ihnen gepostete Code kann nicht kompiliert werden, Ihre 'Ethernet' Klasse hat Slots und' Q_OBJECT' Makro, aber erbt 'QObject' nicht Was ist dein tatsächlicher Code? – ixSci

+0

Vielen Dank für Ihre Antworten. Meine Ethernet-Klasse erbt von QThread, weil es früher ein Thread war, aber nicht mehr. Die eigentliche Implementierung der Klasse ist also "class Ethernet :: public QThread". Ich habe das in der Hauptpost korrigiert. – Puccinih

Antwort

0

Wenn Ihre Klasse nicht ein Thread ist, dann sollte es nicht QThread erben. Erben Sie es von QObject oder, wenn Sie nicht können, starten Sie Ihren M2 Thread. Im Moment funktioniert Ihre Thread-Schleife für die Ethernet nicht und es scheint, wie die Netzwerk-Antworten haben eine Affinität zu Ihrer Ethernet Ereignisschleife (die Anforderungen, sie zu löschen sind in der Ethernet Ereignisschleife, die nicht gestartet wird).

Oder eher, Ihre Slots werden überhaupt nie ausgeführt, so dass die Netzwerkantworten erstellt werden, aber sie werden nie eine Chance haben, gelöscht zu werden, da Ihre Slots nie ausgeführt wurden (aus dem genannten Grund), also wenn ich mich nicht irre Das Netzwerk antwortet live im Hauptthread, sodass deleteLater sie korrekt löschen sollte, aber nie aufgerufen wird.

+0

Ich habe die Ethernet-Klasse in 'class Ethernet: public QObject' geändert, aber das Problem ist immer noch da. – Puccinih

+0

@Puccinih, stelle sicher, dass du einen sauberen Build erstellt hast und dass die Slots "replyAuthenticationRequired" und "replyFinished" – ixSci

+0

aufgerufen wurden. Die Slots wurden von Anfang an aufgerufen, aber das stimmt nur ein paar Mal. Nun, nachdem die Vererbung der Klasse in QObject geändert und ein sauberer Build erstellt wurde, scheint es gelöst zu sein. Ich werde weitere Tests mit dem Server durchführen, um zu sehen, ob es wirklich gut funktioniert. Vielen Dank! – Puccinih

0

Sie benötigen Ethernet Unterklasse von QObject richtig Ereignisschleife verwenden

+0

Er ruft 'QCoreApplication :: exec()' auf, wodurch die Ereignisschleife gestartet wird. –

+0

@KarstenKoop Wenn Ihre Klasse nicht von QObject abgeleitet ist, kann sie keine Ereignisschleife verwenden – tty6

+0

Ereignisschleife ist nicht objektbezogen, daher ist Ihre Antwort irreführend - Sie müssen keine Unterklasse erstellen, um eine Ereignisschleife zu verwenden – ixSci

0

Sie müssen nicht mehrere Objekte von QNetworkAccessManager machen. Wie das Dokument sagt "Ein QNetworkAccessManager sollte genug für die gesamte Qt-Anwendung sein." Reference link. Wenn Sie mehrere Objekte der Ethernet-Klasse erstellen, wird ein Speicherproblem verursacht. Außerdem müssen Sie QObject als Ethernet-Basisklasse definieren.

manager = new QNetworkAccessManager(this); 
this (Ethernet) must have QObject as base class. 
+1

Er hat nur einen Manager – ixSci

Verwandte Themen