简体   繁体   English

当在错误槽中启动事件循环时发生ContentNotFoundError时,QNetworkReply会发出两次错误信号

[英]QNetworkReply emits error signal twice when ContentNotFoundError occures when event loop is started in error slot

Im using QtSDK 4.7.3 我使用QtSDK 4.7.3

I am doing this in (void test()): 我在(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);

And of course the slot onError is called: 当然,调用插槽onError:

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

If i don't have a messagebox/eventloop in the onError slot there is no crash and everything works. 如果我在onError插槽中没有messagebox / eventloop,则没有崩溃,一切正常。 But when it is there then the onError slot gets called again when m.exec() is called. 但是当它存在时,调用m.exec()时会再次调用onError槽。 When both messageboxes are closed and I leave the function onError the application crashes. 当两个消息框都关闭并且我将函数保留为onError时,应用程序崩溃。 The application tries to delete/free memory when this happens. 发生这种情况时,应用程序会尝试删除/释放内存。 The error "Access violation reading location" does not help any and the call stack is deep in to Qt dlls. 错误“访问冲突读取位置”没有任何帮助,调用堆栈深入到Qt dll。

What I have checked: 我检查了什么:
The signal is not connected twice. 信号未连接两次。
Tried calling test() before and after the QApplication calls it's exec function. 尝试在QApplication调用它的exec函数之前和之后调用test()。 (does not matter). (没关系)。
Another error like HostNotFound will not call the onError slot twice. 像HostNotFound这样的另一个错误不会两次调用onError插槽。
All my code is executed in the main thread. 我的所有代码都在主线程中执行。
Tried disconnecting the onError slot so it is only called once but it still crashes. 尝试断开onError插槽,因此只调用一次,但它仍然崩溃。
Tried calling abort on the request in onError(). 试图在onError()中对请求进行中止调用。
Posted the same question on Qt forum ( post ). 在Qt论坛( 帖子 )上发表了同样的问题。

Can anyone help me figure out what is happening here? 任何人都可以帮我弄清楚这里发生了什么?

Here is the code I use for testing: main.cpp 这是我用于测试的代码: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 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;

};

There is a bug in Qt < 4.8.0: https://bugreports.qt.io/browse/QTBUG-16333 Qt <4.8.0中存在一个错误: https ://bugreports.qt.io/browse/QTBUG-16333

Modifying the connection with a queued one solves the problem: 使用排队的连接修改连接可以解决问题:

contentnotfound.h: contentnotfound.h:

#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;

};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM