У меня есть приложение, в котором я выполняю некоторые «синхронные» вызовы с Qt-Qt-классами Qt. Код, который был адаптирован из различных источников в Интернете и выглядит примерно так:Переменные состояния с сетевыми запросами Qt
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!
Я реализовал это, зная, что это был взлом. Я начал задаваться вопросом, могу ли я вместо этого использовать переменные состояния 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 никогда не выполняется. В первом примере событие final(), похоже, срабатывает почти сразу, а QNetworkReply имеет все, что я ожидаю. Почему во втором примере событие pReply final() не вызвано?
Примечание: Я понимаю, что многие люди сильно относятся к синхронным сетевым вызовам, особенно с моделью Qt, которая, очевидно, предназначена для использования асинхронно. Однако это не то, что мне интересно обсуждать с этим вопросом. Спасибо.
Разве я не блокирую текущую нить? Если этот код сам выполняется в другом потоке, цикл событий все равно будет заблокирован? – Addy
@Addy Похоже, вы блокируете тот же поток, где вы вызываете QNetworkAccessManager :: get(), поэтому либо блокируете его поток, либо вы вызываете get из другого потока (и я не думаю, что он потокобезопасен ...) , – hyde
@Addy «Если этот код сам выполняется в другом потоке, цикл событий все равно будет заблокирован?» * Каждый поток имеет цикл событий, но это точка: вы блокируете цикл, который должен доставлять ваш сигнал. – Ilya