在多個線程中使用QNetworkAccessManager


最近發現Tangram發出了URL request, 但是卻收不到URL reponse

經研究后發現這是一個線程問題: Tangram會在多個線程發送URL request, 但是在實現時, 卻沒有考慮線程問題, 程序在運行時得到如下warning:

 

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x21dcba0), parent's thread is QThread(0x20be1c0), current thread is QThread(0x7f48e0044730)

 

在移植Tangram到Qt平台時, 網絡請求使用的是QNetworkAccessManager, QNetworkAccessManager的使用很簡單:

 

  QNetworkAccessManager *manager = new QNetworkAccessManager(this);
  connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
  manager->get(QNetworkRequest(QUrl("http://qt-project.org")));

 

這里碰到的問題是:Tangram可能在多個線程發送URL, 但是QNetworkAccessManager只能在生成它所在的線程中工作, 解決辦法是使用Qt的SIGNAL/SLOT機制, 把該URL request post到正確的線程中:

class URLTaskWorker{
public:
    URLTaskWorker(){
        connect(this,SIGNAL(startRequest()),this, SLOT(onRequest()), Qt::QueuedConnection);
    }
public:
    void handleTask(QUrl url){
        this->url = url;
        emit StartNewRequest();
    }

signals:
    void startRequest();
    
private slots:
    void onRequest(){
        qnam.get(url);
    }

private:
    QNetworkAccessManager   qnam;
    QUrl                    url;
};

 

這里要注意的是, 在connect startRequestonRequest時, 要使用Qt::QueuedConnection, 使用默認的Qt::AutoConnection不工作, 參考Qt幫助文檔:

Qt::QueuedConnection

The slot is invoked when control returns to the event loop of the receiver's thread. The slot is executed in the receiver's thread.

這也是一個Qt的線程安全的在不同線程間傳遞消息的方法。

 


免責聲明!

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



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