2016-03-20 15 views
0

QtのQNetwork *クラスで「同期的な」コールを行うアプリがあります。さまざまなソースからオンラインで適応されたコードは、次のようになります。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++の条件変数を使って同様のことを達成できるかどうか疑問に思った。これは、条件変数を試して初めてですので、私はこれで私は条件変数であることはもちろん_requestCVで正しく(それらを使用しています完全にはよく分からない

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(); 
}); 

:これを試みる私のコードは次のようになります例)。しかし、本当に私が困惑しているのは、QNetworkReply :: finished lambdaは決して実行されないということです。最初の例では、finished()イベントがすぐに起動しているように見えます.QNetworkReplyには、私が期待していたすべてがあります。 2番目の例でpReplyのfinished()イベントが呼び出されないのはなぜですか?

注:同期ネットワークコール、特に非同期で使用するように設計されたQtのモデルについては、多くの人が強く感じていることを理解しています。しかし、それは私がこの質問で議論することに興味があるわけではありません。ありがとうございました。

答えて

1

しかし、本当に私が困惑しているのは、QNetworkReply :: finished ラムダが実行されないことです。

スレッドのイベントループをブロックしています。これは、このイベントループで、finished信号を送信することになっています。イベントループなし、信号なし。

注:私は特に明らかに非同期的に使用されるように を設計されたQtのモデルで、多くの人々が、同期 ネットワーク呼び出しについて強く感じていることを理解しています。

これは、人々がそのように感じる理由の良い例を示しています。

+0

現在のスレッドでのみブロックしていませんか?このコード自体が別のスレッドで実行されると、イベントループはまだブロックされますか? – Addy

+0

@Addy QNetworkAccessManager :: get()を呼び出すと同じスレッドをブロックするように見えるので、スレッドをブロックするか、別のスレッドからgetを呼び出す(スレッドセーフではないと思います...) 。 – hyde

+0

@Addy「このコード自体が別のスレッド上で実行されても、イベントループはブロックされますか?」*各スレッドにはイベントループがありますが、それがポイントです:シグナルを送信するループをブロックしています。 – Ilya