【问题标题】:Condition variables with Qt network requestsQt 网络请求的条件变量
【发布时间】:2016-03-20 21:30:01
【问题描述】:

我有一个应用程序,我在其中使用 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 的模型,它显然是为异步使用而设计的。但是,这不是我有兴趣讨论这个问题的内容。谢谢。

【问题讨论】:

    标签: qt c++11 condition-variable qnetworkreply qnetworkrequest


    【解决方案1】:

    但真正让我感到困惑的是 QNetworkReply::finished lambda 从不执行。

    您正在阻塞线程的事件循环,而这个事件循环应该传递您的finishedsignal。没有事件循环,没有信号。

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

    嗯,你已经举了一个很好的例子来说明人们有这种感觉的原因。

    【讨论】:

    • 我不是只阻塞当前线程吗?如果这段代码本身在不同的线程上执行,事件循环是否仍会被阻塞?
    • @Addy 看起来你阻塞了同一个线程,在那里你调用 QNetworkAccessManager::get(),所以要么阻塞它的线程,要么你从不同的线程调用 get(我不认为它是线程安全的......)。
    • @Addy "如果这段代码本身在不同的线程上执行,事件循环是否仍会被阻塞?"* 每个线程都有它的事件循环,但这就是重点:你阻塞的循环是应该传递你的信号。
    • @Addy 好的 - 我将在答案中添加该位以澄清
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-21
    • 1970-01-01
    • 2020-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多