QNetworkAccessManager的異步與線程


Qt版本5.1.1

以HTTP操作為例

Qt中的HTTP操作都是異步的. 內部通過線程實現

創建線程的時機在QNetworkReplyHttpImplPrivate::postRequest()

void QNetworkReplyHttpImplPrivate::postRequest()
{
    Q_Q(QNetworkReplyHttpImpl);

    QThread *thread = 0;
    if (synchronous) {
        // A synchronous HTTP request uses its own thread
        thread = new QThread();
        thread->setObjectName(QStringLiteral("Qt HTTP synchronous thread"));
        QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
        thread->start();
    } else if (!managerPrivate->httpThread) {
        // We use the manager-global thread.
        // At some point we could switch to having multiple threads if it makes sense.
        managerPrivate->httpThread = new QThread();
        managerPrivate->httpThread->setObjectName(QStringLiteral("Qt HTTP thread"));
        managerPrivate->httpThread->start();

        thread = managerPrivate->httpThread;
    } else {
        // Asynchronous request, thread already exists
        thread = managerPrivate->httpThread;
    }

..........

    // Move the delegate to the http thread
    delegate->moveToThread(thread);
    // This call automatically moves the uploadDevice too for the asynchronous case.

...........
}

 


分為兩種情況:
(1) synchronous == true 每次HTTP請求創建自己的線程, 並在finished后自動退出線程

在QNetworkRequest設置QNetworkRequest::SynchronousRequestAttribute 屬性為真時, synchronous = true, 然而SynchronousRequestAttribute被Qt標記為internal. 以防止外部創建synchronous HTTP請求.
我在Qt的源碼中找到一點說明, QNetworkReplyHttpImpl的構造函數中.

........
   // Internal code that does a HTTP reply for the synchronous Ajax
    // in Qt WebKit.
    QVariant synchronousHttpAttribute = request.attribute(
            static_cast<QNetworkRequest::Attribute>(QNetworkRequest::SynchronousRequestAttribute));
    if (synchronousHttpAttribute.isValid()) {
        d->synchronous = synchronousHttpAttribute.toBool();
........

webkit的ajax請求使用


(2) synchronous == false 則把所有http請求放置在一個線程中.
並且該線程在
QNetworkAccessManagerPrivate對象析構(即QNetworkAccessManager析構)或者調用QNetworkAccessManagerPrivate::clearCache 時退出

QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
{
    if (httpThread) {
        httpThread->quit();
        httpThread->wait(5000);
        if (httpThread->isFinished())
            delete httpThread;
        else
            QObject::connect(httpThread, SIGNAL(finished()), httpThread, SLOT(deleteLater()));
        httpThread = 0;
    }
}

void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
{
    manager->d_func()->objectCache.clear();
    manager->d_func()->authenticationManager->clearCache();

    if (manager->d_func()->httpThread) {
        manager->d_func()->httpThread->quit();
        manager->d_func()->httpThread->wait(5000);
        if (manager->d_func()->httpThread->isFinished())
            delete manager->d_func()->httpThread;
        else
            QObject::connect(manager->d_func()->httpThread, SIGNAL(finished()), manager->d_func()->httpThread, SLOT(deleteLater()));
        manager->d_func()->httpThread = 0;
    }
}

 

否則會一直HTTP 線程會一直存在. 另外, 每個QNetworkAccessManager對象對應自己的HTTP thread.

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM