sleep()//秒
msleep()//毫秒
usleep()//微秒
以前為了模擬鼠標點擊用過這些函數,可以讓進程中斷,今天發現我原來的做法其實不對.
這組函數會將你當前的線程/進程變為“睡眠”狀態。 這個“睡眠”是深度意義的睡眠, 睡眠期間內核不會分配給程序時間片, 所以程序什么都不做, 更不用提界面的刷新了。 直接導致的問題就是用戶無法與程序交互。 所以說直接使用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 { 5 QCoreApplication::processEvents(); 6 }
第二步, 解決程序CPU占用率過高的問題 -- 讓程序適當睡眠。
1 QTimer t; 2 t.start(); 3 while(t.elapsed() < 250) 4 { 5 QCoreApplication::processEvents(); 6 usleep(10000);//sleep和usleep都已經obsolete,Linux下也可以使用nanosleep代替
7 }
以后要用,就可以直接用上面的代碼了,用usleep()就可以了,那個nanosleep()則是Linux中的系統調用,它是使用定時器來實現的,該調用使調用進程睡眠,並往定時器隊列上加入一個timer_list型定時器,time_list結構里包括喚醒時間以及喚醒后執行的函數,通過nanosleep()加入的定時器的執行函數僅僅完成喚醒當前進程的功能。系統通過一定的機制定時檢查這些隊列(比如通過系統調用陷入核心后,從核心返回用戶態前,要檢查當前進程的時間片是否已經耗盡,如果是則調用 schedule()函數重新調度,該函數中就會檢查定時器隊列,另外慢中斷返回前也會做此檢查),如果定時時間已超過,則執行定時器指定的函數喚醒調用進程。當然,由於系統時間片可能丟失,所以nanosleep()精度也不是很高。