这段代码可能会遇到无限循环吗?

时间:2012-05-13 08:01:08

标签: c++ qt concurrency

这个Qt代码是否可能遇到无限循环?

QNetworkAccessManager m;
QNetworkReply *reply = m.get(QNetworkRequest(QUrl("http://www.example.org/")));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
qDebug() << reply->readAll();
delete reply;

这基本上是一种显示网页内容的“同步”方式。

我没有发现任何使用它的问题,但我考虑了以下情况:

  • 在创建事件循环之前发送finished reply的{​​{1}}信号,finishedquit之间的信号槽连接是由
  • 从那一点开始不会发出任何信号,因此永远不会触发quit
  • loop.exec()会不断循环

是否有可能发生这种情况,或者我不了解Qt事件循环的工作原理?

2 个答案:

答案 0 :(得分:1)

当Qt执行您自己的代码(例如上面的代码)时,它无法处理新信号和调用插槽。执行方法时发出的每个信号都将在稍后处理。如果要在方法中间强制处理信号,可以调用QCoreApplication::processEvents来处理当前事件循环中的信号,或QEventLoop::exec在另一个循环中执行此操作。

所以这段代码是安全的。如果信号过快,它将在事件队列中等待。

如果您正在发出信号并且使用Qt::DirectConnection将信号连接到此信号,则这些插槽将立即执行。但这与你的情况不符。 Qt必须在发出信号之前执行一些内部代码。在执行方法时,它无法执行此代码。只有一个线程,只有一个调用堆栈。

请注意,当您使用Qt线程时,事件循环的行为会更复杂。

答案 1 :(得分:-1)

在运行loop.exec()之前,您可以检查reply->isFinished()。如果是,就不要执行循环。