Подтвердить что ты не робот

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

Я использую Qt Creator 1.3.0 с 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)

Что это значит? Как его решить? Спасибо заранее.

4b9b3361

Ответ 1

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

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

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

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