1

我正在尝试使用带有单独线程的 QNetworkAccessManager::get() 下载网页,当我运行程序时,它会随机崩溃(可能是一小时或两小时)。代码示例:

class SpiderThread : public QThread
{   
    Q_OBJECT
public:
    SpiderThread();
    void    run();
private:
    bool    _stopped;
}; 

void SpiderThread::run()
{
    while (!_stopped) {
        DownloadManager downloadManager();
        QUrl u = getOneUrl();
        QString content = downloadManager.getContent(u);
        // some other code
    }
}


QString DownloadManager::getContent(const QUrl &url)
{
    QEventLoop  loop;
    QNetworkAccessManager manager;

    QNetworkRequest request(url);
    request.setRawHeader("User-Agent", _userAgent.toAscii());
    QNetworkReply *reply = manager.get(request);
    connect(reply, SIGNAL(finished()),
            SLOT(replyFinished()));
    connect(reply, SIGNAL(finished()),
            &loop, SLOT(quit()));

    loop.exec();
    if (reply->error() != QNetworkReply::NoError) {
        if (reply->isRunning())
            reply->abort();
        reply->deleteLater();
        return QString();
    }


    int httpCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    if (httpCode != 200)
        return QString();
    QByteArray data = reply->readAll();
    reply->deleteLater();
    return QString(data);
}

我正在使用 QEventloop 阻止 http 请求,直到它完成,当我运行这些代码时,它总是崩溃并显示错误消息:

    纯虚方法调用
    在没有活动异常的情况下调用终止

gdb 调试信息:

    (gdb) BT
    #0 0x0000003c0dc30285 in raise () from /lib64/libc.so.6
    #1 0x0000003c0dc31d30 in abort () from /lib64/libc.so.6
    #2 0x0000003d992bed94 in __gnu_cxx::__verbose_terminate_handler() () 来自 /usr/lib64/libstdc++.so.6
    #3 0x0000003d992bce46 在?? () 来自 /usr/lib64/libstdc++.so.6
    #4 0x0000003d992bce73 in std::terminate() () from /usr/lib64/libstdc++.so.6
    #5 0x0000003d992bd3cf in __cxa_pure_virtual () from /usr/lib64/libstdc++.so.6
    #6 0x00002aaaabc3cc35 在 QCoreApplication::postEvent(QObject*, QEvent*, int) ()
           来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtCore.so.4
    #7 0x00002aaaabc5301d in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) ()
           来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtCore.so.4
    #8 0x00002aaaab7b81a1 在?? () 来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #9 0x00002aaaab7ac3ad 在?? () 来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #10 0x00002aaaab7c8d1d 在 ?? () 来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #11 0x00002aaaab7cadb0 在 ?? () 来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #12 0x00002aaaab7a89ce 在 QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) ()
          来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #13 0x00002aaaab7a5ea4 在 QNetworkAccessManager::get(QNetworkRequest const&) ()
                     来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtNetwork.so.4
    #14 0x00000000004088fe 在 DownloadManager::getContent (this=0x409fff40, url=..., toCodec=...)
                         在 src/downloadmanager.cpp:55
    #15 0x0000000000415248 在 SpiderThread::run (this=0x7ffffffffe2b0) at src/spiderthread.cpp:27
    #16 0x00002aaaabb2c3b9 在?? () 来自 /usr/local/Trolltech/Qt-4.8.2/lib/libQtCore.so.4
    #17 0x0000003c0e40677d in start_thread () from /lib64/libpthread.so.0
    #18 0x0000003c0dcd325d in clone () from /lib64/libc.so.6

请帮助我,我花了这么多时间来找出问题所在,但它仍然不起作用。我犯了一些错误?

4

1 回答 1

2

你把事情不必要地复杂化了。默认实现QThread::run()已经创建并运行了一个事件循环。不要从 QThread 派生。将您的功能放入 QObject 中,并moveToThread(thread)在启动线程后调用该对象,如有必要!使用信号和插槽来完成任务。QNetworkAccessManager 已经使用了工作线程 IIRC,因此在另一个专用线程中创建它可能毫无意义。

于 2012-06-11T16:14:05.063 回答