Qt:使用QEventLoop等待信号,如果信号发得太早怎么办?

时间:2017-03-04 06:40:09

标签: c++ qt slot qt-signals

我正在开发一个小型客户端 - 服务器应用程序。客户端发送查询并且必须等待答复。我认为最方便的方法是使用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吗?

谢谢!

1 个答案:

答案 0 :(得分:4)

鉴于您的代码,您遇到问题的唯一方法是在调用answer_received()之前发出loop.exec()信号。这相当于在调用answer_received()期间发出this.sendQuery();

在您的情况下,由于您依赖服务器/客户端交互并且您可能使用某种QNetworkAccessManagerQSocket,因此不太可能发生这种情况。如果是这种情况,QNetworkAccessManager / QSocket将不会发出readyRead()finished()信号,直到您进入事件循环。

但是,在更一般的情况下,如果answer_received()可以从this.sendQuery()发出,则必须更改代码:

  1. 您可以在排队之间建立连接。这种方式即使在answer_received()期间发出this.sendQuery(),在您进入事件循环之前也不会调用该插槽。

    connect(&parser, SIGNAL(answer_received()), &loop, SLOT(quit()), Qt::QueuedConnection);
    
  2. 您可以确保answer_received()期间永远不会发出this.sendQuery()。在这样做的方法是使用0ms QTimer,它将在事件队列中的所有事件被处理后立即触发,即在loop.exec()期间

    替换:

    emit answer_received();
    

    人:

    QTimer::singleShot(0, this, *receiver, &MyClass::answer_received);