Qt程式進入等待睡眠的正確方法

pamxy發表於2013-07-30

轉自:http://mobile.51cto.com/hot-238884.htm

Qt程式執行的時候等待一段時間, 這段時間裡可能程式什麼都不做,也可能是在後臺開了個子執行緒在做一些使用者看不見的工作。當我們使用使用類似linux提供的”sleep”或”usleep”函式時很容易造成使用者無法與程式互動,本文將告訴你一個正確的方法。

AD: 2013雲端計算架構師峰會超低價搶票中

51CTO編者按:Qt框架是Symbian應用程式開發和MeeGo應用程式開發的主要框架,我們在編寫Qt程式時經常會遇到這樣的需求: 讓程式等待一段時間, 這段時間裡可能程式什麼都不做, 也可能是在後臺開了個子執行緒在做一些使用者看不見的工作。

首先我們容易想到的方法是使用類似linux提供的”sleep”或”usleep”函式。 但用過這組函式的Qter都知道, 這組函式會將你當前的執行緒/程式變為“睡眠”狀態。 這個“睡眠”是深度意義的睡眠, 睡眠期間核心不會分配給程式時間片, 所以程式什麼都不做, 更不用提介面的重新整理了。 直接導致的問題就是使用者無法與程式互動。 所以說直接使用sleep函式睡眠是常見的錯誤方案之一。

另外一種更常見的錯誤方法是使用QTimer+死迴圈。 類似下面的程式碼:

  1. QTimer t; 
  2. t.start(); 
  3. while(t.elapsed() < 250); 

這個簡單粗暴的解決方案也是行不通的。 從程式碼中我們可以發現在while迴圈中不停的呼叫elapsed()函式, 等於在這段時間內CPU完全沒有機會做別的什麼事情。 特別是在Linux這樣非搶佔式的作業系統中, 這樣的死迴圈造成的影響是致命的, CPU被完全佔用, 核心都沒有機會排程程式, 別的程式拿不到時間片執行, 系統基本上就是癱瘓狀態了。 無論如何, 這種結果都不是我們想要的。(當然拉, 除非你想寫的是病毒程式。) 對於我們的程式本身, 雖然它佔用了所有的CPU, 但由於它陷入該迴圈, 程式沒有機會進入到GUI事件迴圈, 導致同樣介面是無法重新整理的。

其實把上面的程式碼稍加改變就能得到一個很好的解決方案。 第一步, 解決介面無法重新整理的問題。 呼叫QCoreApplication::processEvents(), 程式碼如下:

  1. QTimer t; 
  2. t.start(); 
  3. while(t.elapsed() < 250
  4. QCoreApplication::processEvents(); 

第二步, 解決程式CPU佔用率過高的問題 -- 讓程式適當睡眠。

  1. QTimer t; 
  2. t.start(); 
  3. while(t.elapsed() < 250
  4. QCoreApplication::processEvents(); 
  5. usleep(10000);//sleep和usleep都已經obsolete,建議使用nanosleep代替 

這裡設定程式睡眠一段很短很短的時間, 對於使用者來說是不會有什麼感覺的, 但對核心來說就意義大不同。 這樣核心就有充足的時間排程程式/執行緒, 讓其他程式有機會執行。

在Qt裡其實是提供了類似的API的, 只是不在core或gui庫裡, 而是在QTestLib中。 參考下面的文件:http://doc.qt.nokia.com/4.6/qtest.html#qWait


相關文章