由于开发需求,需要在子线程中实现高频采用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便在同一个线程中。
上述分析也存在许多疑问,主要是不断尝试获得的结果。有关多线程中变量所属线程还请移步参考: