<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                #(68):訪問網絡(4) 前面幾章我們了解了如何使用`QNetworkAccessManager`?訪問網絡。在此基礎上,我們已經實現了一個簡單的查看天氣的程序。在這個程序中,我們使用`QNetworkAccessManager`進行網絡的訪問,從一個網絡 API 獲取某個城市的當前天氣狀況。 如果你仔細觀察就會發現,即便我們沒有添加任何相關代碼,`QNetworkAccessManager`的網絡訪問并不會阻塞 GUI 界面。也就是說,即便是在進行網絡訪問的時候,我們的界面還是可以響應的。相比之下,如果你對 Java 熟悉,就會了解到,在 Java 中,進行 Socket 通訊時,界面默認是阻塞的,當程序進行網絡訪問操作時,界面不能對我們的操作做出任何響應。由此可以看出,`QNetworkAccessManager`的網絡訪問默認就是異步的、非阻塞的。這樣的實現固然很好,也符合大多數程序的應用情形:我們當然希望程序界面能夠始終對用戶操作做出響應。不過,在某些情況下,我們還是希望會有一些同步的網絡操作。典型的是登錄操作。在登錄時,我們必須要等待網絡返回結果,才能讓界面做出響應:是驗證成功進入系統,還是驗證失敗做出提示?這就是本章的主要內容:如何使用`QNetworkAccessManager`進行同步網絡訪問。 當我們重新運行先前編譯好的程序,可以看看這樣一個操作:由于我們的界面是不阻塞的,那么當我們第一次點擊了 Refresh 按鈕之后,馬上切換城市再點擊一次 Refresh 按鈕,就會看到第一次的返回結果一閃而過。這是因為第一次網絡請求尚未完成時,用戶又發送了一次請求,Qt 會將兩次請求的返回結果順序顯示。這樣處理結果可能會出現與預期不一致的情況(比如第一次請求響應由于某種原因異常緩慢,第二次卻很快,此時第二次結果會比第一次先到,那么很明顯,當第一次結果返回時,第二次的結果就會被覆蓋掉。我們假設認為用戶需要第二次的返回,那么就會出現異常)。 要解決這種情況,我們可以在有網絡請求時將界面鎖死,不允許用戶進行更多的操作(更好的方法是僅僅鎖住某些按鈕,而不是整個界面。不過這里我們以鎖住整個界面為例)。我們的解決方案很簡單:當`QNetworkAccessManager`發出請求之后,我們進入一個新的事件循環,將操作進行阻塞。我們的代碼示例如下: ~~~ void fetchWeather(const QString &cityName) { QEventLoop eventLoop; connect(netWorker, &NetWorker::finished, &eventLoop, &QEventLoop::quit); QNetworkReply *reply = netWorker->get(QString("http://api.openweathermap.org/data/2.5/weather?q=%1&mode=json&units=metric&lang=zh_cn").arg(cityName)); replyMap.insert(reply, FetchWeatherInfo); eventLoop.exec(); } ~~~ 注意,我們在函數中創建了一個`QEventLoop`實例,將其`quit()`與`NetWorker::finished()`信號連接起來。當`NetWorker::finished()`信號發出時,`QEventLoop::quit()`就會被調用。在`NetWorker::get()`執行之后,調用`QEventLoop::exec()`函數開始事件循環。此時界面就是被阻塞。 現在我們只是提供了一種很簡單的思路。當然這并不是最好的思路:程序界面直接被阻塞,用戶獲得不了任何提示,會誤以為程序死掉。更好的做法是做一個恰當的提示,不過這已經超出我們本章的范疇。更重要的是,這種思路并不完美。**如果你的程序是控制臺程序(沒有 GUI 界面),或者是某些特殊的情況下,會造出死鎖!**控制臺程序中發送死鎖的原因在于在非 GUI 程序中另外啟動事件循環會將主線程阻塞,`QNetworkAccessManager`的所有信號都不會收到。“某些特殊的情況”,我們會在后面有關線程的章節詳細解釋。不過,要完美解決這個問題,我們必須使用另外的線程。[這里](http://www.codeproject.com/Articles/484905/Use-QNetworkAccessManager-for-synchronous-download)有一個通用的解決方案,感興趣的童鞋可以詳細了解下。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看