处理QThread

时间:2016-09-28 18:42:03

标签: qt

我试图在Qt工作线程中处理http-post响应。我试图以推荐的方式做到这一点,即我按如下方式创建一个帖子:

_thread = new QThread;
_worker = new Worker(this);
_worker->moveToThread(_thread);
// start the worker thread
connect(_thread, SIGNAL(started()), _worker, SLOT(process()));

然后在函数process中执行以下操作:

do {
    QNetworkAccesManger netw;
    // init req (headers) and payload
    //....
    QNetworkReply *reply = newt.post(req, payload);
    connect(reply, SIGNAL(readyRead()), SLOT(onReadyRead()), Qt::DirectConnection);
    connect(reply, SIGNAL(finished()), SLOT(onFinished()), Qt::DirectConnection);
    QThread::msleep(200);
} while (!terminate);

onReadyReadonFinished是工作对象中的插槽。问题是永远不会调用onReadyReadonFinished。我相信这是因为我没有处理while循环中的事件。

我尝试过类似的方法,而不是使用moveToThread我直接将QThread子类化,这样一切都按预期工作。我假设这是因为QThread :: run调用exec()以处理事件。

但是我认为继承QThread并不是推荐的方式,有人可以解释我在这里缺少的东西吗?

1 个答案:

答案 0 :(得分:2)

  

我相信这是因为我不是在处理这些事件   循环。

你说得对,这是因为你永远不会处理线程中的事件。但是,你错了,你应该在while循环中这样做。

让我们来看看这里发生了什么。通常,当QThread启动时,在新线程中调用run()函数(如果它尚未被覆盖)调用exec()exec()函数为线程提供了一个事件循环,这是线程应该处理事件的地方

在您的代码中,发出started()(请注意,甚至在调用run()函数之前就会发生这种情况),这会导致调用Worker::process()函数。并且由于您的process()实现永远不会返回(除非需要终止线程),您的线程永远不会进入事件循环来处理事件(因为它始终在您的{{中执行do-while循环1}}实现)和process无法告诉它有它的新信号。

结论:

你应该从不拥有一个永远不会在事件驱动系统中返回的功能。您应该尽快从函数返回,以便事件循环可以处理挂起的事件。

如果您的意思是每QNetworkAccessManagerdo-while循环执行200循环中的代码,您应该使用QTimer,将其timeout()信号连接到应该是的插槽每隔200 msecs执行一次,然后start()执行200 msecs。

所以,以下是您的代码的样子:

_thread = new QThread;
_worker = new Worker(this);
_worker->moveToThread(_thread);
// start the worker thread
//calling init instead of process
//init will be responsible to schedule calls to "process" every 200 msecs
connect(_thread, SIGNAL(started()), _worker, SLOT(init()));

init函数看起来像这样:

QTimer* timer= new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(process()));
//call "process" slot every 200 msecs
timer->start(200);
//call "process" the first time
process();

process广告位现在简单得多:

QNetworkAccesManger netw;
// init req (headers) and payload
//....
QNetworkReply *reply = newt.post(req, payload);
connect(reply, SIGNAL(readyRead()), SLOT(onReadyRead()), Qt::DirectConnection);
connect(reply, SIGNAL(finished()), SLOT(onFinished()), Qt::DirectConnection);