【问题标题】:QObject: Cannot create children for a parent that is in a different threadQObject:无法为不同线程中的父级创建子级
【发布时间】:2011-03-17 03:13:00
【问题描述】:

我在 Windows 7 Ultimate 下使用 Qt 4.6.0(32 位)。考虑以下QThread

界面

class ResultThread : public QThread
{
Q_OBJECT

    QString _post_data;
    QNetworkAccessManager _net_acc_mgr;

signals:
    void onFinished(QNetworkReply* net_reply);

private slots:
    void onReplyFinished(QNetworkReply* net_reply);

public:
    ResultThread();

    void run();
    void setPostData(const QString& post_data);
};

实施

ResultThread::ResultThread() : _net_acc_mgr(this)
{
    connect(&_net_acc_mgr, SIGNAL(finished(QNetworkReply*)),
            this, SLOT(onReplyFinished(QNetworkReply*)));
}

void ResultThread::onReplyFinished(QNetworkReply* net_reply)
{
    emit onFinished(net_reply);
}

void ResultThread::setPostData(const QString& post_data)
{
    _post_data = post_data;
}

void ResultThread::run()
{
    _net_acc_mgr.post(QNetworkRequest(QUrl("http://[omitted]")),
                      QByteArray(_post_data.toStdString().c_str()));
}

每当在ResultThread::run() 中执行_net_acc_mgr.post() 时,我都会在Qt Creator 中得到以下应用程序输出:

QObject:无法为不同线程中的父级创建子级。

(Parent是QNetworkAccessManager(0x22fe58),parent的线程是QThread(0x9284190),当前线程是ResultThread(0x22fe48)

这是什么意思?如何解决?

【问题讨论】:

    标签: c++ qt


    【解决方案1】:

    run() 成员函数在不同的线程中执行,而不是在创建QNetworkRequestManager 对象的线程中执行。

    当您使用多个线程时,Qt 总是会出现这种不同线程的问题。解决此问题的规范方法是使用 signalsslots

    QNetworkRequestManager所属的对象中创建一个slot,在ResultThread中创建一个signal并将两者连接起来, ResultThread 的构造函数会是个好地方。

    当前在 ResultThread::run() 中的代码进入新的 slot,并被 emit(yourSignal()) 替换。如有必要,将指向您的 ResultThread 的指针作为参数与您的发出函数一起发送,以访问成员函数/变量。

    【讨论】:

    • 这可行,但对我来说看起来很奇怪。我在ResultThread 中声明了_net_acc_mgr,但ResultThread::run() 在另一个线程中执行!为什么Qt是这样设计的?特别是,为什么ResultThread::run() 运行在另一个线程而不是ResultThread
    • 欢迎来到多线程的世界。实际上,创建 ResultThread 的线程总是与执行 ResultThread::run() 的线程不同。想一想,其他方式都没有意义。 QThread 的全部目的是在不同的线程中运行某些东西。为此,您需要在某处为新线程设置数据,这发生在您创建 ResultThread 的线程中。完成后,您就可以运行该线程了——当然它会在另一个线程中运行...
    • 那么,如果所有的代码都被移动到槽中,那么槽就会在父线程中执行。为什么要创建子线程?
    • 您可能误解了如何使用 QThread。在您的情况下,最好不要实现 run 方法,而是将 worker QObject(必须与 QThread 对象不同)移动到 QThread。查看文档中的示例:doc.qt.io/qt-5/qthread.html#details
    猜你喜欢
    • 2016-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多