gpt4 book ai didi

qt - QObject 无法为处于不同线程中的父对象创建子对象

转载 作者:行者123 更新时间:2023-12-04 09:58:11 28 4
gpt4 key购买 nike

您好,我需要从后台进行一些套接字通信,我为此使用了QtConcurrent::run,但给了我警告。

QObject: Cannot create children for a parent that is in a different thread.
(Parent is MainWindow(0x7fff3e69f500), parent's thread is QThread(0x16f8070), current thread is QThread(0x17413d0)

这是代码,

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),ui(new Ui::MainWindow){
ui->setupUi(this);
QFuture<void> f2 = QtConcurrent::run(this,&MainWindow::checkCamStatus);
}


void MainWindow::checkCamStatus(){
while(1){
bool flag = false;
QTcpSocket* socket = new QTcpSocket(this);
socket->moveToThread(this->thread());
socket->setParent(this);
socket->connectToHost("10.0.7.112", 80);
if(socket->waitForConnected(1000))//check for connection for i second
{
qDebug() << "Cam online";
}
else{
qDebug() << "..............................Cam offline";
}

QThread::sleep(1);
}
}

如何删除警告?

最佳答案

首先,你的代码有什么问题:

不能在new QTcpSocket(this)中使用this,因为this->thread()不是当前线程(QThread::currentThread()).

不能在socket->moveToThread(this->thread())之后调用socket的任何函数成员,因为socket->thead() 不再是当前线程。

这已记录在案 here :

Event driven objects may only be used in a single thread. Specifically, this applies to the timer mechanism and the network module. For example, you cannot start a timer or connect a socket in a thread that is not the object's thread.

现在,如果您只想连接一个 TCP 套接字而什么都不做,您可以做的是修复您的代码,就是删除对 this 的任何引用并执行类似的操作:

void MainWindow::checkCamStatus(){
while(1){
bool flag = false;
QScopedPointer<QTcpSocket> socket(new QTcpSocket());
socket->connectToHost("10.0.7.112", 80);
if(socket->waitForConnected(1000))//check for connection for i second
{
qDebug() << "Cam online";
}
else{
qDebug() << "..............................Cam offline";
}

QThread::sleep(1);
}
}

但是,如果你想用 TCP 套接字做一些其他事情,比如发送或接收数据,你最好将你的代码包装在一个类中:

class CamWatcher : public QObject
{
Q_OBJECT
public:
CamWatcher(QObject *parent = 0) :
QObject(parent),
m_socket(new QTcpSocket(this))
{}
QTcpSocket *socket() { return m_socket; }

public slots:
void tryConnect() { socket->connectToHost("10.0.7.112", 80); }

private slots:
void onSocketConnected() { qDebug() << "Connected"; }
void onSocketDisconnected() { qDebug() << "Disconnected"; }
void onSocketError(QAbstractSocket::SocketError socketError)
{
qWarning() << m_socket->errorString();
}
private:
QTcpSocket *m_socket = nullptr;
}

这样您就可以将所有 TCP 内容(监控、数据传输等)放入一个对象中。您可以将它放在与 MainWindow 相同的线程中,但如果需要,您也可以将它放在另一个线程中。

请注意,如果您在 MainWindow 之外的另一个线程中有 CamWatcher,但您想要调用 CamWatcher 的函数,则必须执行如下操作:

QTimer::singleshot(0, camwatcher, &CamWatcher::tryConnect);
QMetaObject::invokeMethod(camwatcher, "tryConnect", Qt::QueuedConnection); // No compile time check, works only with slots
QMetaObject::invokeMethod(camwatcher, &CamWatcher::tryConnect, Qt::QueuedConnection); // Requires Qt 5.10

关于qt - QObject 无法为处于不同线程中的父对象创建子对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47449312/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com