• 7151阅读
  • 2回复

这个是不是QNetworkAccessManager的一个bug [复制链接]

上一主题 下一主题
离线zooood
 
只看楼主 倒序阅读 楼主  发表于: 2012-05-03
把一个QNetworkAccessManager对象用moveToThread()函数move到一个新线程的时候
貌似move得不彻底。QNetworkAccessManager内部的某些子对象不会move到新线程

先上代码,不长
运行的时候最好把网断了,这样结果看得更清楚一些

myobject.h:
  1. #ifndef MYOBJECT_H
  2. #define MYOBJECT_H
  3. #include <QObject>
  4. #include <QtNetwork/QNetworkAccessManager>
  5. #include <QtNetwork/QNetworkReply>
  6. #include <QtNetwork/QNetworkRequest>
  7. #include <QDebug>
  8. #include <QThread>
  9. #include <QEventLoop>
  10. class MyObject : public QObject
  11. {
  12. Q_OBJECT
  13. public:
  14. explicit MyObject(QObject *parent = 0):QObject(parent){
  15. manager = new QNetworkAccessManager(this);
  16. }
  17. public slots:
  18. void work(){
  19. qDebug() << "current thread: " << QThread::currentThread();
  20. qDebug() << "manager's thread: " << manager->thread();
  21. manager->get(QNetworkRequest(QUrl([url]http://www.baidu.com[/url])));
  22. QEventLoop loop;
  23. loop.exec();
  24. }
  25. private:
  26. QNetworkAccessManager * manager;
  27. };
  28. #endif // MYOBJECT_H


main.cpp:
  1. #include <QtCore/QCoreApplication>
  2. #include <myobject.h>
  3. #include <QThread>
  4. #include <QDebug>
  5. #include <QMetaObject>
  6. int main(int argc, char *argv[])
  7. {
  8. QCoreApplication a(argc, argv);
  9. qDebug() << "main thread: " << QThread::currentThread();
  10. MyObject object;
  11. QThread thread;
  12. object.moveToThread(&thread);
  13. thread.start();
  14. QMetaObject::invokeMethod(&object, "work", Qt::QueuedConnection);
  15. return a.exec();
  16. }

输出:
main thread:  QThread(0xa02a28)
current thread:  QThread(0x28fea8)
manager's thread:  QThread(0x28fea8)
QObject::startTimer: timers cannot be started from another thread

注意最后一行的QObject::startTimer: timers cannot be started from another thread
这一行是在网络访问结束并返回时,发生的warning。意思是说定时器在另一个线程中发起,而这个是Qt不允许的。
另一个线程是哪个线程呢?可能是主线程,也可能是QNetworkAccessManager内部实现异步的线程。但我觉得是前者
如果是后者,那在主线程中使用QNetworkAccessManager也会出现同样的问题,但经验上没出现过这种问题。所以推断是前者
离线fish0619

只看该作者 1楼 发表于: 2012-05-03
为什么要移到新线程?看看Qt的多线程文章,有提到,在一个线程中创建的`QObject`对象不能在另外一个线程里面使用。如果一个程序的代码里面出现`moveToThread()`,多半是错了。
离线zooood
只看该作者 2楼 发表于: 2012-05-03
不是不能移动到新线程,而是移动有前提:
一个QObject对象的parent如果不是0,就不能移动

这是因为Qt认为同一棵对象树上的所有QObject对象都必须属于同一个线程

对于moveToThread(),这是qt帮助文档里推荐的做法
快速回复
限100 字节
 
上一个 下一个