QNetworkReply дважды выдает сигнал об ошибке, когда возникает ContentNotFoundError, когда цикл обработки событий запускается в слоте ошибки

Я использую QtSDK 4.7.3

Я делаю это в (void test()):

mgr = new QNetworkAccessManager();
reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));

connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
    SLOT(onError(QNetworkReply::NetworkError)), Qt::ConnectionType::UniqueConnection);

И, конечно же, слот onError называется:

if (networkError == QNetworkReply::NetworkError::ContentNotFoundError)
{
// Messagebox starts an event loop which
// causes this slot to be called again
QMessageBox m;
m.exec();
}

Если у меня нет окна сообщений/цикла событий в слоте onError, сбоя не происходит, и все работает. Но когда он есть, слот onError снова вызывается при вызове m.exec(). Когда оба окна сообщений закрыты, и я оставляю функцию onError, приложение вылетает. Приложение пытается удалить/освободить память, когда это происходит. Ошибка «Место чтения нарушения доступа» не помогает, а стек вызовов находится глубоко в dll Qt.

Что я проверил:
Сигнал не подключается дважды.
Пытался вызывать test() до и после того, как QApplication вызывает свою функцию exec. (не имеет значения).
Другая ошибка, такая как HostNotFound, не будет вызывать слот onError дважды.
Весь мой код выполняется в основном потоке.
Пытался отключить слот onError, поэтому он вызывается только один раз, но все равно вылетает.
Пытался вызвать прерывание по запросу в onError().
Тот же вопрос опубликован на форуме Qt (сообщение).

Может ли кто-нибудь помочь мне понять, что здесь происходит?

Вот код, который я использую для тестирования: main.cpp

#include "contentnotfound.h"
#include <QtGui/QApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);

ContentNotFound cnf;

// false: start test after application's event loop have started
if (true) { cnf.test(); }
else { QTimer::singleShot(2000, &cnf, SLOT(test())); }

return a.exec();
}

contentnotfound.h

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMessageBox>

class ContentNotFound : public QObject
{
Q_OBJECT

public slots:
void test()
{
    mgr = new QNetworkAccessManager();
    reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));

    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
        SLOT(onError(QNetworkReply::NetworkError)), Qt::ConnectionType::UniqueConnection);
}

private slots:
void onError(QNetworkReply::NetworkError networkError)
{
    //reply->disconnect(); // Disconnect all signals

    if (networkError == QNetworkReply::NetworkError::ContentNotFoundError)
    {
        // Messagebox starts an event loop which
        // causes this slot to be called again
        QMessageBox m;
        m.exec();
    }
}

private:
QNetworkAccessManager* mgr;
QNetworkReply* reply;

};

person Elon Mallin    schedule 04.10.2011    source источник


Ответы (1)


В Qt ‹ 4.8.0 есть ошибка: https://bugreports.qt.io/browse/QTBUG-16333

Изменение соединения с очередью решает проблему:

содержание не найдено.ч:

#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMessageBox>

class ContentNotFound : public QObject
{
Q_OBJECT

public slots:
void test()
{
    qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
    mgr = new QNetworkAccessManager(this);
    reply = mgr->get(QNetworkRequest(QUrl("http://developer.qt.nokia.com/fileNotExisting.txt")));

    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
        SLOT(onError(QNetworkReply::NetworkError)), Qt::QueuedConnection);
}

private slots:
void onError(QNetworkReply::NetworkError networkError)
{
    //reply->disconnect(); // Disconnect all signals

    if (networkError == QNetworkReply::ContentNotFoundError)
    {
        // Messagebox starts an event loop which
        // causes this slot to be called again
        QMessageBox m;
        m.exec();
    }
}

private:
QNetworkAccessManager* mgr;
QNetworkReply* reply;

};
person Paolo Brandoli    schedule 04.10.2011
comment
Спасибо за ваш очень быстрый ответ. Это работает. Для уточнения в решении также добавлена ​​эта строка: qRegisterMetaType‹QNetworkReply::NetworkError›(QNetworkReply::NetworkError); Другое решение можно найти в отчете об ошибке, на который вы ссылаетесь, но это решение лучше. В отчете об ошибке также говорится, что в Qt 4.8.0 эта ошибка будет исправлена. - person Elon Mallin; 05.10.2011