【问题标题】:QNetworkReply emits error signal twice when ContentNotFoundError occures when event loop is started in error slot当在错误槽中启动事件循环时发生 ContentNotFoundError 时,QNetworkReply 发出两次错误信号
【发布时间】:2011-11-30 20:19:56
【问题描述】:

我使用的是 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 插槽中没有消息框/事件循环,则不会发生崩溃并且一切正常。但是当它在那里时,当调用 m.exec() 时会再次调用 onError 插槽。 当两个消息框都关闭并且我离开函数 onError 时,应用程序崩溃。 发生这种情况时,应用程序会尝试删除/释放内存。错误“访问冲突读取位置”无济于事,调用堆栈深入 Qt dll。

我检查过的内容:
信号没有连接两次。
尝试在 QApplication 调用它的 exec 函数之前和之后调用 test()。 (没关系)。
另一个类似 HostNotFound 的错误不会调用 onError 槽两次。
我所有的代码都在主线程中执行。
尝试断开 onError 插槽,因此它只被调用一次,但它仍然崩溃。
尝试在 onError() 中对请求调用中止。
在 Qt 论坛 (post) 上发布了同样的问题。

谁能帮我弄清楚这里发生了什么?

这是我用于测试的代码: 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;

};

【问题讨论】:

    标签: c++ qt runtime-error qnetworkaccessmanager event-loop


    【解决方案1】:

    Qt https://bugreports.qt.io/browse/QTBUG-16333

    使用排队的连接修改连接可以解决问题:

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

    【讨论】:

    • 感谢您的快速回复。这行得通。为了清楚起见,在解决方案中还添加了这一行: qRegisterMetaType<:networkerror>("QNetworkReply::NetworkError");在您链接到的错误报告中可以找到另一个解决方案,但这个解决方案更好。错误报告还说,在 Qt 4.8.0 中,这个错误将得到修复。
    猜你喜欢
    • 2021-05-02
    • 2023-02-23
    • 1970-01-01
    • 2017-12-30
    • 2018-08-18
    • 1970-01-01
    • 2019-03-20
    • 2013-11-25
    • 2022-01-10
    相关资源
    最近更新 更多