0

我有一个应用程序,我在其中使用 Qt 的 QNetwork* 类进行一些“类似同步”的调用。从网上各种来源改编的代码看起来像:

QNetworkRequest request("http://www.somedomain.com");
QNetworkReply* pReply = _manager->get(request); 

// A not-so-great-solution to wait for the request, but works
QEventLoop loop;
QObject::connect(pReply, SIGNAL(finished()), &loop, SLOT(quit()), Qt::DirectConnection);
loop.exec(QEventLoop::ExcludeUserInputEvents);

// Now the pReply object has what I want, yay!

我知道这是一个hack,所以我实现了这个。我开始想知道是否可以改用 C++ 的条件变量来实现类似的效果。我尝试这样做的代码如下所示:

QNetworkRequest request("http://www.somedomain.com");
QNetworkReply* pReply = _manager->get(request);

QObject::connect(pReply, &QNetworkReply::finished,
    [this]()
    {
        std::unique_lock<std::mutex> lock(_requestMutex);
        _requestCV.notify_one();
    });

std::unique_lock<std::mutex> lock(_requestMutex);
_requestCV.wait(lock, [this, pReply]()
{
    return pReply->isFinished();
});

这是我第一次尝试条件变量,所以我不完全确定我是否正确使用它们(_requestCV当然在这个例子中是条件变量)。但真正让我困惑的是 QNetworkReply::finished lambda 永远不会执行。在第一个示例中,finished() 事件似乎几乎立即触发,并且 QNetworkReply 具有我所期望的一切。为什么在第二个示例中从未调用 pReply 的 finished() 事件?

注意:我知道很多人对同步网络调用有强烈的感觉,尤其是 Qt 的模型显然是为异步使用而设计的。但是,这不是我有兴趣讨论这个问题的内容。谢谢你。

4

1 回答 1

1

但真正让我困惑的是 QNetworkReply::finished lambda 永远不会执行。

您正在阻塞线程的事件循环,这就是应该传递finished信号的事件循环。没有事件循环,没有信号。

注意:我知道很多人对同步网络调用有强烈的感觉,尤其是 Qt 的模型显然是为异步使用而设计的。

嗯,你已经给出了一个很好的例子来说明人们为什么会有这种感觉。

于 2016-03-20T21:47:36.147 回答