QObject: Невозможно создать дочерние элементы для родителя, который находится в другом потоке - PullRequest
46 голосов
/ 16 июля 2010

Я использую Qt 4.6.0 (32 бит) под Windows 7 Ultimate.Рассмотрим следующее 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()));
}

Всякий раз, когда _net_acc_mgr.post() выполняется в ResultThread::run(), я получаю следующий вывод приложенияв Qt Creator:

QObject: Невозможно создать дочерние элементы для родителя, который находится в другом потоке.

(Parent - QNetworkAccessManager (0x22fe58), родительский поток - QThread (0x9284190),текущая тема ResultThread (0x22fe48)

Что это значит? Как ее решить?

1 Ответ

55 голосов
/ 16 июля 2010

Функция-член run () выполняется в другом потоке, а не в потоке, в котором был создан объект QNetworkRequestManager.

Подобные проблемы с различными потоками возникают постоянно с Qt , когда вы используете несколько потоков. Каноническим способом решения этой проблемы является использование сигналов и слотов .

Создайте слот в объекте, к которому принадлежит QNetworkRequestManager, создайте сигнал в ResultThread и соедините оба где-нибудь, конструктор ResultThread было бы хорошим местом.

Код, который в данный момент находится в ResultThread :: run () , отправляется в новый слот и заменяется на emit(yourSignal()). При необходимости отправьте указатель на ваш ResultThread в качестве параметра с вашей функцией emit, чтобы получить доступ к функциям / переменным-членам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...