【问题标题】:Cannot create children for a parent that is in a different thread (Qt)无法为不同线程中的父级创建子级(Qt)
【发布时间】:2012-11-13 13:31:20
【问题描述】:

我目前在 Qt 中遇到了一个奇怪的问题。 我有一个使用 QTcpSocket 处理多个客户端的应用程序。 客户端向服务器提供登录详细信息,服务器正在检查 MySQL 数据库以在单独的线程上验证凭据。

我有 2 个不同的客户端程序登录到此服务器 1. 一个使用 Qt 连接的简单客户端 2. C-Sharp (.net) 编码的客户端

然而

当第二个客户端尝试登录服务器时,我在服务器上收到一条错误消息,告诉我:

QObject:无法为不同线程中的父级创建子级。 Parent是QNativeSocketEngine(0x1231e00),parent的线程是 QThread(0xc625f0),当前线程为CMySQLHandler(0xc67188)

我猜这发生在 MySQL 处理程序线程上 但奇怪的是,在 Qt 编码的客户端上根本没有发生这种情况

代码如下:

void CMySQLHandler::onAuthRequest(ulong clientID, QString email, QString psw, QString HWID, QString ip)
{

    string pass = "", salt = "", name = "", avatar = "";
    uint UserID = 0;
    CUserData *extra = new CUserData();
    bool success = false;
    QString failReason = "Success";

    string Query = "SELECT password, username, avatar, userid FROM jos_users LEFT JOIN jos_community_users ON jos_users.id = jos_community_users.userid WHERE email = '"+email.toStdString()+"'";
    SQLRow Row = GetRow(Query);

    if(!Row.empty())
    {
        QString hashedPass = QString(Row[0].c_str());
        pass = hashedPass.split(':').at(0).toStdString();
        salt = hashedPass.split(':').at(1).toStdString();


        name = Row[1];
        avatar = Row[2];
        UserID = QString(Row[3].c_str()).toUInt();
        QByteArray data;
        data.append((psw + QString(salt.c_str())));
        QString blah = QString(QCryptographicHash::hash(data,QCryptographicHash::Md5).toHex());
        if(QString(pass.c_str()) == blah )
            success = true;
        else
            failReason = "Invalid password";

    }
    else
    {
        failReason = "E-Mail not found";
        emit Handle->onAuthCompleted(clientID, false, failReason, extra);
        return;
    }

    extra->Avatar += avatar.c_str();
    extra->UserID = UserID;

    extra->Username = QString(name.c_str());

    emit Handle->onAuthCompleted(clientID, true, QString(), extra);
}

这是信号定义

void CMySQLHandler :: onTimerInit()
{

    //Authentication
    connect(this, SIGNAL(doAuthCompleted(ulong,bool,QString,CUserData*)), Handle, SLOT(onAuthCompleted(ulong,bool,QString,CUserData*)));
    connect(Handle, SIGNAL(doRequestAuth(ulong,QString,QString,QString,QString)), this, SLOT(onAuthRequest(ulong,QString,QString,QString,QString)));
    //end


    CMySQL::Init(Handle);
}

我是 Qt 框架的新手。 请原谅缺乏知识。

感谢您抽出宝贵时间阅读本文。

【问题讨论】:

    标签: c++ mysql qt


    【解决方案1】:

    Qt 使用线程拥有对象的概念。线程自己的对象来做信号/槽机制。问题是您试图在线程 CMySQLHandler(0xc67188) 中创建一个新对象并将其分配给父 QNativeSocketEngine(0x1231e00)。但是 QNativeSocketEngine 归 QThread(0xc625f0) 所有,这是不允许的。我在您的代码中看不到错误,因此您可能需要进行更多调试以找到导致错误的行并编辑您的问题。

    【讨论】:

    • 我称之为 void DoAuth(ulong id, QString email, QString pass, QString hwid, QString ip) { emit doRequestAuth(id, email, pass, hwid, ip);可能是因为我从非 qobject 对象调用它?
    【解决方案2】:

    当您使用多线程时,这种不同线程问题在 Qt 中总是会发生。解决这个问题的规范方法是使用信号和槽。

    onAuthRequest 中没有发生该错误,它可能更早,您尝试调用此函数。也许您正在一个线程中创建CMySQLHandler 对象,并尝试在另一个线程中执行它的成员函数。

    如果您出于某种原因需要调用属于不同威胁的对象的函数,请在包装该函数的对象中创建slot,并使用emit 调用它。

    查看类似问题QObject: Cannot create children for a parent that is in a different thread

    【讨论】:

    • 是的,但这是在 QT 编码客户端上工作的唯一一次是当我使用 C-sharp 编码客户端尝试它时。它们都发送相同的数据并执行相同的例程。会不会是对“emit doAuthRequest()”的调用来自非 QObject 类?
    • 经过一些调试后,我注释掉了 (Handle->onAuthCompleted(clientID, true, QString(), extra);) 似乎是它造成的。
    猜你喜欢
    • 1970-01-01
    • 2011-03-17
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多