我正在尝试在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);
onReadyRead
和onFinished
是辅助对象中的插槽。 问题是永远不会调用onReadyRead
或onFinished
。 我相信这是因为我没有在while循环中处理事件。
我尝试了一种类似的方法,在该方法中,一切都按预期工作,而不是直接使用moveToThread
来moveToThread
QThread,而不是使用moveToThread
。 我认为这是因为QThread :: run调用exec()来处理事件。
但是我认为不推荐使用QThread的子类化,任何人都可以解释我在这里缺少的内容吗?
我相信这是因为我没有在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);