tags:

views:

80

answers:

1

I am using Qt Creator 1.3.0 with Qt 4.6.0 (32 bit) under Windows 7 Ultimate. Consider the following QThread:

Header

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);
};

Implementation

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()));
}

Whenever _net_acc_mgr.post() is executed in ResultThread::run(), I got the following Application Output in Qt Creator:

QObject: Cannot create children for a parent that is in a different thread.

(Parent is QNetworkAccessManager(0x22fe58), parent's thread is QThread(0x9284190), current thread is ResultThread(0x22fe48)

What does this mean? How to solve it? Thanks in advance.

+2  A: 

The run() member function is executed in a different thread, rather than the thread where QNetworkRequestManager object was created.

This kind of different-thread problems happen all the time with Qt when you use multiple threads. The canonical way to solve this problem is to use signals and slots.

Create a slot in the object where QNetworkRequestManager belongs to, create a signal in ResultThread and connect both of the somewhere, the constructor of ResultThread would be a good place.

The code which is currently in ResultThread::run() goes to the new slot, and is replaced by a emit(yourSignal()). If neccessary send a pointer to your ResultThread as a parameter with your emit function to gain access to member funtions/variables.

drhirsch
This works but looks weird to me. I declared _net_acc_mgr inside `ResultThread` but `ResultThread::run()` executes in another thread! Why Qt is designed in this way? Particularly, why `ResultThread::run()` runs in another thread rather than `ResultThread`?
Donotalo
Welcome to the world of multithreading. Actually, the thread in which ResultThread is created is always different to the one, where ResultThread::run() is executed. Think about it, it doesn't make sense any other way.The whole purpose of QThread is to run something in a different thread. To do this, you need to set up the data for the new thread somewhere and this happens in the thread where you create ResultThread. When this is done, you are able to run the thread - of course it runs then in a different thread...
drhirsch