在QThread内部处理http-post(QnetworkAccessManager :: post)响应

问题描述 投票:0回答:1

我正在尝试在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循环中处理事件。

我尝试了一种类似的方法,在该方法中,一切都按预期工作,而不是直接使用moveToThreadmoveToThread QThread,而不是使用moveToThread 。 我认为这是因为QThread :: run调用exec()来处理事件。

但是我认为不推荐使用QThread的子类化,任何人都可以解释我在这里缺少的内容吗?

qt
1个回答
2
投票

我相信这是因为我没有在while循环中处理事件。

您是对的,这是因为您从不处理线程中的事件。 但是,您应该在while循环中执行此操作是错误的。

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

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

结论:

永远不应该拥有一个在事件驱动的系统中永不返回的函数。 您应该始终从函数中尽快返回,以便事件循环可以处理未决事件。

如果您打算每200毫秒执行一次do-while循环中的代码,则应使用QTimer ,将其timeout()信号连接到应每200毫秒执行一次的插槽,然后以200的间隔start()毫秒

因此,代码如下所示:

_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);
© www.soinside.com 2019 - 2024. All rights reserved.