0
点赞
收藏
分享

微信扫一扫

QNetworkAccessManager多线程下引发QObject: Cannot create children for a parent that is in a different threa

东言肆语 2022-04-13 阅读 74
qtc++

由于开发需求,需要在子线程中实现高频采用QNetworkAccessManager::get方法获取数据。基于Qt的代码结构如下:
子线程类中:

post_thread_test.h:

class post_thread_test : public QObject
{
	Q_OBJECT

public:
	post_thread_test(QObject *parent = Q_NULLPTR);
	
	~post_thread_test();
	void post_collect(QVector<QString>*);

public slots:
	void finishedSlot2(QNetworkReply *reply);

private:
	QVector<QString> post_thread_vec;
	QNetworkAccessManager* accessManager2;
	QNetworkRequest* request2;
};

post_thread_test.cpp:

post_thread_test::post_thread_test(QObject *parent)
	: QObject(parent)
{
	request2 = new QNetworkRequest();//此处要标明变量的父对象
	accessManager2 = new QNetworkAccessManager();//确保accessManager2与equest2都是在主线程中声明的变量
	request2->setUrl(QUrl("http://wthrcdn.etouch.cn/weather_mini?citykey=101020100"));
	request2->setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
	connect(accessManager2, SIGNAL(finished(QNetworkReply*)), this, SLOT(finishedSlot2(QNetworkReply*)));
}

void post_thread_test::post_collect(QVector<QString>* vec_p )
{
	//进入这个函数中再声明的变量就是子线程中的变量

	while (n < 100)
	{
		n++;
		accessManager2->get(*request2);
		QTime dieTime = QTime::currentTime().addMSecs(100);//更改此处,单位为ms
		while (QTime::currentTime() < dieTime)
			QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
	}
	//accessManager2->get(*request2);
}

void post_thread_test::finishedSlot2(QNetworkReply *reply)
{
	qDebug() << "ost_thread_vec" << post_thread_vec;
	if (reply->error() == QNetworkReply::NoError)
	{
		QByteArray bytes = reply->readAll();
		QJsonObject get_json;
		get_json = QJsonDocument::fromJson(bytes).object();
		qDebug() << "thread_get_json: " << get_json.value("desc").toString();

	}
	else
	{
		qDebug() << "finishedSlot errors here" << reply->error();
		qDebug("found error .... code: %d\n", (int)reply->error());
		qDebug(qPrintable(reply->errorString()));
	}
	reply->deleteLater();
}

主线程中:

QThread *post_thread;
post_thread_test* mythreadT;

mythreadT->moveToThread(post_thread);
post_thread->start();
thread_vec->push_back("132");
emit ex_post_thread(thread_vec);

上述代码的逻辑是,在主线程中触发子线程,进入子线程函数post_thread_test::post_collect后会高频发送get请求,每次获得数据后则会触发post_thread_test::finishedSlot2函数响应请求。而依照上述代码,会出现警告:

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

这是由于request2与accessManager2不在一个线程中。request2在主线程中,而accessManager2在子线程中(具体为何accessManager2会在子线程中也不是很明白)。
实际上,线程类post_thread_test在程序最开始是在主线程进行的初始化。当启动子线程后,accessManager2被放入了子线程,因此二者不在同一个线程中。
要取消这个警告,可在post_thread_test.cpp初始化accessManager2时声明其父对象:

accessManager2 = new QNetworkAccessManager(this);

这样request2与accessManager2便在同一个线程中。
上述分析也存在许多疑问,主要是不断尝试获得的结果。有关多线程中变量所属线程还请移步参考:

举报

相关推荐

0 条评论