在多个线程中使用QNetworkAccessManager

Posted btian

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在多个线程中使用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), parents 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 receivers thread. The slot is executed in the receivers thread.

这也是一个Qt的线程安全的在不同线程间传递消息的方法。

 

以上是关于在多个线程中使用QNetworkAccessManager的主要内容,如果未能解决你的问题,请参考以下文章

在多个线程中使用QNetworkAccessManager

在 C++ 中,如何使用多个线程读取一个文件?

核心数据 - 在多个线程之间共享 NSManagedObjects

在eclipse中调试多个线程

多线程 Win32 C++ 程序在多个线程中使用 try/catch 崩溃

如何使用CSV数据集配置在Jmeter的不同线程中使用不同输入登录多个用户