Qt程序進入等待睡眠的正確方法
51CTO編者按:Qt框架是Symbian應用程序開發和MeeGo應用程序開發的主要框架,我們在編寫Qt程序時經常會遇到這樣的需求: 讓程序等待一段時間, 這段時間里可能程序什么都不做, 也可能是在后臺開了個子線程在做一些用戶看不見的工作。
首先我們容易想到的方法是使用類似linux提供的”sleep”或”usleep”函數。 但用過這組函數的Qter都知道, 這組函數會將你當前的線程/進程變為“睡眠”狀態。 這個“睡眠”是深度意義的睡眠, 睡眠期間內核不會分配給程序時間片, 所以程序什么都不做, 更不用提界面的刷新了。 直接導致的問題就是用戶無法與程序交互。 所以說直接使用sleep函數睡眠是常見的錯誤方案之一。
另外一種更常見的錯誤方法是使用QTimer+死循環。 類似下面的代碼:
- QTimer t;
- t.start();
- while(t.elapsed() < 250);
這個簡單粗暴的解決方案也是行不通的。 從代碼中我們可以發現在while循環中不停的調用elapsed()函數, 等于在這段時間內CPU完全沒有機會做別的什么事情。 特別是在Linux這樣非搶占式的操作系統中, 這樣的死循環造成的影響是致命的, CPU被完全占用, 內核都沒有機會調度進程, 別的程序拿不到時間片執行, 系統基本上就是癱瘓狀態了。 無論如何, 這種結果都不是我們想要的。(當然拉, 除非你想寫的是病毒程序。) 對于我們的程序本身, 雖然它占用了所有的CPU, 但由于它陷入該循環, 程序沒有機會進入到GUI事件循環, 導致同樣界面是無法刷新的。
其實把上面的代碼稍加改變就能得到一個很好的解決方案。 第一步, 解決界面無法刷新的問題。 調用QCoreApplication::processEvents(), 代碼如下:
- QTimer t;
- t.start();
- while(t.elapsed() < 250)
- {
- QCoreApplication::processEvents();
- }
第二步, 解決程序CPU占用率過高的問題 -- 讓程序適當睡眠。
- QTimer t;
- t.start();
- while(t.elapsed() < 250)
- {
- QCoreApplication::processEvents();
- usleep(10000);//sleep和usleep都已經obsolete,建議使用nanosleep代替
- }
這里設置程序睡眠一段很短很短的時間, 對于用戶來說是不會有什么感覺的, 但對內核來說就意義大不同。 這樣內核就有充足的時間調度進程/線程, 讓其他程序有機會執行。
在Qt里其實是提供了類似的API的, 只是不在core或gui庫里, 而是在QTestLib中。 參考下面的文檔:http://doc.qt.nokia.com/4.6/qtest.html#qWait
這個函數是專為Qt測試提供, 所以不建議直接使用在Qt程序中。 不過它的基本實現差不多就是我們上面列出的代碼, 很簡單, copy paste到程序里用就好了。
Phone Club——51CTO移動開發線下技術沙龍
本期主題:Android應用開發技術進階
地點:北京市海淀區中關村南大街30號東聯藝術工社
演講講師:范懷宇(網易)
【編輯推薦】
- QTreeWidget設計解決沒有拖動項問題
- Symbian和MeeGo將統一開發環境 Qt壓力很大
- QtCreator:MeeGo開發程序入門手冊
- 諾基亞發布Qt 4.6版本 支持多點觸摸和手勢輸入
- 在QT SDK下構建MeeGo Touch開發環境