0

У меня есть приложение, в котором я выполняю некоторые «синхронные» вызовы с 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, которая, очевидно, предназначена для использования асинхронно. Однако это не то, что мне интересно обсуждать с этим вопросом. Спасибо.

ответ

1

Но что действительно меня озадачило, так это то, что QNetworkReply :: finished lambda никогда не выполняет.

Вы блокируете цикл событий в своем потоке, и этот цикл событий должен доставлять ваш сигнал finished. Нет цикла событий, нет сигнала.

Примечание: Я понимаю, что многие люди сильно о синхронных сетевых вызовов, особенно с моделью Qt, которая, очевидно, предназначен для использования в асинхронном режиме.

Хорошо, вы дали хороший пример причин, по которым люди так чувствуют себя.

+0

Разве я не блокирую текущую нить? Если этот код сам выполняется в другом потоке, цикл событий все равно будет заблокирован? – Addy

+0

@Addy Похоже, вы блокируете тот же поток, где вы вызываете QNetworkAccessManager :: get(), поэтому либо блокируете его поток, либо вы вызываете get из другого потока (и я не думаю, что он потокобезопасен ...) , – hyde

+0

@Addy «Если этот код сам выполняется в другом потоке, цикл событий все равно будет заблокирован?» * Каждый поток имеет цикл событий, но это точка: вы блокируете цикл, который должен доставлять ваш сигнал. – Ilya

 Смежные вопросы

  • Нет связанных вопросов^_^