QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNetworkAccessManager(0x17d16c88), parent's thread is QThread(0x1643ab88), current thread is QThread(0x17d16cd8)
有可能大家在利用qt写程序的时候遇到这类提醒,这事实上是在说父类和子类的线程不对。
下面是我没解决错误前的代码
thread_http = new QThead;
thread_query = new QThead;
httpA = new HttpGP;
seriportQuery = new SeriportQuery;
httpA->moveToThread(thread_http);
//httpA->accessManager->moveToThread(thread_http);
seriportQuery->moveToThread(thread_query);
thread_http->start();
thread_query->start();
我线性的认为把一个类放到线程里那么相关的内部一切都放到子线程中了,结果就是那么尴尬出现了上面的错误。
解决方案:就是把相关类内部的生成的对象
1 要么在实例化时声明父类
2 要么在移入线程之后再实例化
下面就是我在 HttpGP 这个类实例化时,同时实例化了一个 QNetworkAccessManager
的类
testA = new QNetWorkAccessManager(); //这种方式实例化 testA 的父类与 HttpGP 的父类一致,所以在一致的时候产生了线程异常的问题,采用下面提到的方式就可以解决。
这里指出,QNetworkAccessManager 也是一个独立的类并不从属HttpGP 这个类,所以它实际在工作在主线程,而执行完上述代码后HttpGP执行在子线程中,线程不匹配导致了错误的出现。
方法一:解决的办法就是让QNetworkAccessManager也移到HttpGP所在的线程
httpA->accessManager->moveToThread(thread_query);//就是解决方法
方法二:另外就是在声明后面加入(this)
accessManager = new QNetworkAccessManager(this);
方法三:如果你在run()中实现的,那就是在run内实例化
方法四:就是完成 httpA->moveToThread() 这一步之前,不要去实例化类,可以用单次定时器触发一个函数在函数里面实例化类,这样就有一个时间差足够程序完成 httpA->moveToThread() ;
方法五:通过信号和槽的方式,比较安全和稳定,等到线程移植完成之后,再去触发实例化的函数
QMetaObject::invokeMethod 需要说明的是,这是一种比较简单调用其他类或者线程槽函数,信号的方法,但是这种方法不会检查对象是否存在,也就是说存在对象已经释放但是仍去调用,导致异常的问题
这种情况,就比较适合用传统的 connect, emit 了