c++ - 对象:无法为位于不同线程中的父级创建子级
问题描述
我正在使用:
Qt Creator 3.0.1
Based on Qt 5.2.1 (GCC 4.8.2, 32 bit)
Built on Apr 9 2014 at 09:14:10
此版本是 ACR890 一体化移动智能卡终端 SDK 的一部分。
手机正在运行 linux,我不是发行版,如果我运行:
uname -a:
我得到:
Linux am37x-evm 2.6.37 #1 Wed Nov 22 18:16:43 HKT 2017 armv7l GNU/Linux
在我的应用程序中,我创建了一个工作线程来检查 WiFi 网络的状态:
mpWiFiScan = new clsWiFiScan(this);
//Connect slot to scan signal
connect(mpWiFiScan, SIGNAL(scanResultsReady(QString))
,this, SLOT(networkScanResults(QString)));
mpWiFiScan->setScanState(SS_SCAN);
mpWiFiScan->start();
这在主窗口构造函数的末尾被调用。在主窗口类中,我有接收网络扫描结果的插槽:
void clsMainWnd::networkScanResults(QString strResults) {
qDebug() << "clsMainWnd::networkScanResults:";
qDebug() << strResults;
}
这是 WiFi 扫描线程主体:
void clsWiFiScan::run() {
int intSleepCounter = 0;
bool blnLastPowerState;
QString strResponse;
while ( true ) {
eScanState eState = eGetScanState();
if ( eState == SS_TERMINATE ) {
break;
}
if ( eState != SS_SCAN ) {
continue;
}
bool blnPower = blnGetPowerStatus();
if ( blnPower != true ) {
//Is the "wpa_supplicant" process running?
if ( clsSOAP::lngPIDof(this, lsWiFiScan::mscstrWPAsupplicant) == 0 ) {
//No, start it now
mpcAcsWiFi->reloadWpaSupplicant();
}
//Can we ping Google?
if ( clsSOAP::blnPingTest(this) != true ) {
//No, ensure WiFi power is on
wifi_pwr_on();
}
//Can we get a server response?
strResponse = mpcAcsWiFi->status();
if ( strResponse.contains("wpa_state=COMPLETED") ) {
//Yes, turn on power
setPower(true);
}
while ( eState != SS_TERMINATE
&& eState != SS_PAUSE
&& intSleepCounter < mscintReloadWPAsupplicantTime) {
sleep(mscintTempSleepDuration);
intSleepCounter += mscintTempSleepDuration;
eState = eGetScanState();
}
if ( intSleepCounter == mscintReloadWPAsupplicantTime ) {
setPower(true);
}
intSleepCounter = 0;
}
//If the power was off and now its on...
if ( blnLastPowerState != true && blnGetPowerStatus() == true ) {
mpcAcsWiFi->scan();
strResponse = mpcAcsWiFi->scanResults();
emit scanResultsReady(strResponse);
while ( eState != SS_TERMINATE
&& eState != SS_PAUSE
&& intSleepCounter < mscintScanInterval ) {
sleep(mscintTempSleepDuration);
intSleepCounter += mscintTempSleepDuration;
eState = eGetScanState();
}
}
//Update the last known power state
blnLastPowerState = blnPower;
intSleepCounter = 0;
}
emit scanFinished();
delete mpcAcsWiFi;
setScanState(SS_TERMINATED);
}
问题是当我运行这个应用程序时,我会看到很多以下内容:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is clsWiFiScan(0xd8208), parent's thread is Thread(0xb8c38), current thread is clsWiFiScan(0xd8208)
然后后来:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0xd82e8), parent's thread is Thread(0xb8c38), current thread is clsWiFiScan(0xd8208)
QProcess 在函数中被调用:
bool clsSOAP::blnPingTest(QObject* pParent, QString strURL) {
QProcess* pProc = new QProcess(pParent);
pProc->start("ping", QStringList() << "-c" << "1" <<
"-w" << "10" <<
strURL);
while( pProc->waitForFinished() != true ) {
}
int intExitCode = pProc->exitCode();
delete pProc;
return (intExitCode == 0);
}
对于 Google,strURL 的默认值为 8.8.8.8。
long clsSOAP::lngPIDof(QObject* pParent, QString strApp) {
QProcess* pProc = new QProcess(pParent);
pProc->start("pidof", QStringList() << strApp);
while( pProc->waitForFinished() != true ) {
}
QByteArray bytOutput = pProc->readAllStandardOutput();
bool blnOk;
long lngPID = bytOutput.trimmed().toLong(&blnOk);
delete pProc;
return lngPID;
}
一切似乎都正常,但我仍然收到很多这些警告。
[编辑] 根据评论,我更改了我的类,因此它现在派生自 QObject,而不是 QThread。
现在是这样写的:
mpWiFiScan = new clsWiFiScan(this);
//In the clsWiFiScan constructor it calls setParent(pParent); where pParent the passed parameter
mpWiFiScan->moveToThread(&mthrdWiFiScan);
//mthrdWiFiScan is a member variable of type QThread
connect(&mthrdWiFiScan, SIGNAL(started())
,mpWiFiScan, SLOT(run()));
connect(mpWiFiScan, SIGNAL(scanFinished())
,&mthrdWiFiScan, SLOT(quit()));
connect(mpWiFiScan, SIGNAL(scanFinished())
,&mthrdWiFiScan, SLOT(deleteLater()));
connect(&mthrdWiFiScan, SIGNAL(finished())
,&mthrdWiFiScan, SLOT(deleteLater()));
mthrdWiFiScan.start();
我仍然收到相同的消息,我根本没有看到 run() 被调用。
解决方案
您可以通过调用QObject::moveToThread()然后设置父对象来解决这些问题。
例如,您创建 WiFi 扫描仪的代码会像这样改变。
mpWiFiScan = new clsWiFiScan();
mpWiFiScan->moveToThread(QApplication::instance()->thread());
mpWiFiScan->setParent(this);
//Connect slot to scan signal
connect(mpWiFiScan, SIGNAL(scanResultsReady(QString))
,this, SLOT(networkScanResults(QString)));
mpWiFiScan->setScanState(SS_SCAN);
mpWiFiScan->start();
推荐阅读
- rundeck - 作业条件报告以前的作业“从不运行”
- unity3d - Unity2D 没有正确检查条件
- mongodb - Docker中的SpringBoot未连接到Mongo并引发异常
- amazon-web-services - Amazon Elastic Container Service 中的无法拉取容器错误
- mysql - MySql关于状态的触发函数
- swift - 删除所有注释(MyPointAnnotations),其中 type != something
- windows - Windows终端可点击的网址?
- visual-studio-code - VSCode状态栏一半隐藏在任务栏下方
- django - 如何在 AllAuth 社交帐户注册上进行自定义重定向
- reactjs - 视图之间几乎重复的状态