2016-05-10 5 views
0

Я разрабатываю приложение, которое отправляет запросы на сервер с помощью QtNetworkAccessManager и сохраняет ответы. Я заработал, но использование памяти постоянно увеличивается, и оно блокирует весь компьютер. Я думаю, что проблема связана с вызовом deleteelater() и цикла событий, но я не вижу, как это исправить. Вот код:Проблемы с памятью QNetworkAccessManager

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(); 
} 

Я признателен за любые предложения. Спасибо!

+0

У вас нет цикла событий в вашем классе Ethernet, поэтому deleteLater - не работает – tty6

+0

Код, который вы опубликовали, не может быть скомпилирован, ваш класс 'Ethernet' имеет слоты и макрос' Q_OBJECT', но не наследует 'QObject', каков ваш фактический код? – ixSci

+0

Благодарим вас за ответы. Мой класс Ethernet наследуется от QThread, потому что он был потоком, но не больше. Таким образом, реальной реализацией класса является «class Ethernet :: public QThread». Я исправил в главном посте. – Puccinih

ответ

0

Если ваш класс не является нитью, он не должен наследовать QThread. Наследуйте его от QObject или, если вы не можете, запустите свой поток M2. Прямо сейчас ваш цикл потока для Ethernet не работает , и похоже, что сетевые ответы имеют сродство к вашему циклу событий Ethernet (запросы на их удаление отправляются в цикл событий Ethernet, который не запущен).

Вернее, ваши слоты никогда не выполняются вообще, поэтому сетевые ответы создаются, но у них никогда не будет возможности быть удаленными, поскольку ваши слоты никогда не выполняются (из-за указанной причины), поэтому, если я не ошибаюсь сеть отвечает в основном потоке, поэтому deleteLater должен правильно удалить их, но он никогда не вызывается.

+0

Я изменил класс Ethernet на класс class: public QObject, но проблема все еще существует. – Puccinih

+0

@Puccinih, убедитесь, что вы сделали чистую сборку, и что 'replyAuthenticationRequired' и' replyFinished' слоты получаются вызванными – ixSci

+0

Слоты вызывались с самого начала, но это правда, что всего несколько раз. Теперь, после изменения наследования класса в QObject и создания чистой сборки, он, кажется, решается. Я сделаю еще одно тестирование с сервером, чтобы убедиться, что он действительно работает нормально. Спасибо! – Puccinih

0

Вам нужно подкласс Ethernet от QObject использовать цикл событий правильно

+0

Он называет 'QCoreApplication :: exec()', который запускает цикл события. –

+0

@KarstenKoop, если ваш класс не подклассифицирован из QObject, он не может использовать цикл событий – tty6

+0

Цикл событий не связан с объектами, поэтому ваш ответ вводит в заблуждение - вам не нужно подклассировать что-либо для использования цикла событий – ixSci

0

Вы не должны сделать несколько объектов QNetworkAccessManager. Как говорится в документе: «Один QNetworkAccessManager должен быть достаточным для всего приложения Qt». Reference link. Если вы создадите несколько объектов класса Ethernet, это создаст проблему с памятью. И вам также необходимо сделать QObject как базовый класс Ethernet.

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

У него есть только один менеджер – ixSci

Смежные вопросы