时间:2021-07-01 10:21:17 帮助过:69人阅读
经研究后发现这是一个线程问题: Tangram会在多个线程发送URL request, 但是在实现时, 却没有考虑线程问题, 程序在运行时得到如下warning:
- QObject: Cannot create children <span style="color: #0000ff">for</span> a parent that <span style="color: #0000ff">is</span> <span style="color: #0000ff">in</span><span style="color: #000000"> a different thread.
- (Parent </span><span style="color: #0000ff">is</span> QNetworkAccessManager(<span style="color: #800080">0x21dcba0</span>), parent<span style="color: #800000">‘</span><span style="color: #800000">s thread is QThread(0x20be1c0), current thread is QThread(0x7f48e0044730)</span>
在移植Tangram到Qt平台时, 网络请求使用的是QNetworkAccessManager, QNetworkAccessManager的使用很简单:
- QNetworkAccessManager *manager = <span style="color: #0000ff">new</span> QNetworkAccessManager(<span style="color: #0000ff">this</span><span style="color: #000000">);
- connect(manager, SIGNAL(finished(QNetworkReply</span>*<span style="color: #000000">)), th</span><span style="color: #0000ff">is</span>, SLOT(replyFinished(QNetworkReply*<span style="color: #000000">)));
- manager</span>-><span style="color: #0000ff">get</span>(QNetworkRequest(QUrl(<span style="color: #800000">"</span><span style="color: #800000">http://qt-project.org</span><span style="color: #800000">"</span>)));
这里碰到的问题是:Tangram可能在多个线程发送URL, 但是QNetworkAccessManager只能在生成它所在的线程中工作, 解决办法是使用Qt的SIGNAL/SLOT机制, 把该URL request post到正确的线程中:
- <span style="color: #0000ff">class</span><span style="color: #000000"> URLTaskWorker{
- </span><span style="color: #0000ff">public</span><span style="color: #000000">:
- URLTaskWorker(){
- connect(</span><span style="color: #0000ff">this</span>,SIGNAL(startRequest()),<span style="color: #0000ff">this</span><span style="color: #000000">, SLOT(onRequest()), Qt::QueuedConnection);
- }
- </span><span style="color: #0000ff">public</span><span style="color: #000000">:
- </span><span style="color: #0000ff">void</span><span style="color: #000000"> handleTask(QUrl url){
- </span><span style="color: #0000ff">this</span>->url =<span style="color: #000000"> url;
- emit StartNewRequest();
- }
- signals:
- </span><span style="color: #0000ff">void</span><span style="color: #000000"> startRequest();
- </span><span style="color: #0000ff">private</span><span style="color: #000000"> slots:
- </span><span style="color: #0000ff">void</span><span style="color: #000000"> onRequest(){
- qnam.</span><span style="color: #0000ff">get</span><span style="color: #000000">(url);
- }
- </span><span style="color: #0000ff">private</span><span style="color: #000000">:
- QNetworkAccessManager qnam;
- QUrl url;
- };</span>
这里要注意的是, 在connect startRequest和onRequest时, 要使用Qt::QueuedConnection, 使用默认的Qt::AutoConnection不工作, 参考Qt帮助文档:
- <span style="color: #000000">Qt::QueuedConnection
- </span><span style="color: #000000">
- The slot </span><span style="color: #0000ff">is</span> invoked when control returns to the <span style="color: #0000ff">event</span> loop of the receiver<span style="color: #800000">‘</span><span style="color: #800000">s thread. The slot is executed in the receiver</span><span style="color: #800000">‘</span>s thread.
这也是一个Qt的线程安全的在不同线程间传递消息的方法。
在多个线程中使用QNetworkAccessManager
标签:nal ssm pos repo 文档 manage object 不同 mon