Qt:使用QEventLoop等待信号,如果信号发射得太早怎么办?
Qt: Waiting for a signal using QEventLoop, what if the signal is emitted too early?
我正在开发一个小型客户端-服务器应用程序。客户端发送一个查询,必须等待一个答案。我认为最方便的方法是使用 QEventLoop:
connect(&parser, SIGNAL(answer_received()), this, SLOT(react_to_answer()));
...
...
QEventLoop loop;
connect(&parser, SIGNAL(answer_received()), &loop, SLOT(quit()));
this.sendQuery();
loop.exec();
目前这对我有用,但是如果信号 answer_received()
发出得非常快,甚至在调用 loop.exec()
之前,会发生什么情况?我的应用程序会永远卡在 QEventLoop 中吗?
谢谢!
根据您的代码,您遇到问题的唯一方法是在调用 loop.exec()
之前发出 answer_received()
信号。这相当于说 answer_received()
在调用 this.sendQuery();
.
期间发出
在您的情况下,这不太可能发生,因为您依赖 server/client 交互并且您可能使用某种 QNetworkAccessManager
或 QSocket
。如果是这种情况,QNetworkAccessManager/QSocket 将不会发出 readyRead()
或 finished()
信号,直到您进入事件循环。
但是,在更一般的情况下,如果 answer_received()
可以从 this.sendQuery()
发出,您必须更改代码:
您可以让连接排队。这样,即使 answer_received()
在 this.sendQuery()
期间发出,插槽也不会被调用,直到您进入事件循环。
connect(&parser, SIGNAL(answer_received()), &loop, SLOT(quit()), Qt::QueuedConnection);
您可以确保在 this.sendQuery()
期间永远不会发出 answer_received()
。这样做的方法是使用 0ms QTimer,它会在事件队列中的所有事件都被处理后立即触发,即在 loop.exec()
期间
替换:
emit answer_received();
作者:
QTimer::singleShot(0, this, *receiver, &MyClass::answer_received);
我正在开发一个小型客户端-服务器应用程序。客户端发送一个查询,必须等待一个答案。我认为最方便的方法是使用 QEventLoop:
connect(&parser, SIGNAL(answer_received()), this, SLOT(react_to_answer()));
...
...
QEventLoop loop;
connect(&parser, SIGNAL(answer_received()), &loop, SLOT(quit()));
this.sendQuery();
loop.exec();
目前这对我有用,但是如果信号 answer_received()
发出得非常快,甚至在调用 loop.exec()
之前,会发生什么情况?我的应用程序会永远卡在 QEventLoop 中吗?
谢谢!
根据您的代码,您遇到问题的唯一方法是在调用 loop.exec()
之前发出 answer_received()
信号。这相当于说 answer_received()
在调用 this.sendQuery();
.
在您的情况下,这不太可能发生,因为您依赖 server/client 交互并且您可能使用某种 QNetworkAccessManager
或 QSocket
。如果是这种情况,QNetworkAccessManager/QSocket 将不会发出 readyRead()
或 finished()
信号,直到您进入事件循环。
但是,在更一般的情况下,如果 answer_received()
可以从 this.sendQuery()
发出,您必须更改代码:
您可以让连接排队。这样,即使
answer_received()
在this.sendQuery()
期间发出,插槽也不会被调用,直到您进入事件循环。connect(&parser, SIGNAL(answer_received()), &loop, SLOT(quit()), Qt::QueuedConnection);
您可以确保在
期间this.sendQuery()
期间永远不会发出answer_received()
。这样做的方法是使用 0ms QTimer,它会在事件队列中的所有事件都被处理后立即触发,即在loop.exec()
替换:
emit answer_received();
作者:
QTimer::singleShot(0, this, *receiver, &MyClass::answer_received);