不同編程語言的Delay函數分別是什麼?
小弟不才,前幾個月在玩Arduino,最近打算玩玩樹莓派。和大多數編程語言不同,Arduino的編程語言(一種類C語言)是有delay函數的,延遲的時間單位是毫秒。
之前在給我的小機器人寫上位機程序的時候,就發現Visual Basic .Net沒有delay函數,最後索性拿了一個timer來解決問題。當我現在打算寫C和Python的時候,尷尬的事情發生了,沒有delay函數可以用。我曾經在網上搜索,答案是要自己建一個函數,不停的循環。所以我有點好奇,為什麼大多數編程語言都沒有delay。「大多數編程語言」包括C,VB .Net和JAVA。小弟不才,希望各位大大解答小弟的疑惑。
原問題:
---------------- 分割線 ----------------
先問是不是,再問為什麼。以下代碼均可延時(約)0.5秒。
C++(Windows):
#include &
Sleep(500);
C++(Linux):
#include &
usleep(500000);
C++(C++11):
#include &
#include &
std::this_thread::sleep_for(500ms);
Python:
import time
time.sleep(0.5)
Java:
Thread.sleep(500);
怎麼會沒有呢(
順便在電腦上用循環來延時是不推薦的,一是因為可能會不準,二是因為會一直佔用CPU資源。用 sleep 的話程序是不會佔用CPU的,等到一定時候會自動被操作系統喚醒。
這是操作系統的功能,和語言沒什麼關係。
首先還是那句話——先問是不是,再問為什麼
考慮語言默認的基礎庫的情況下,有沒有語言是有延遲功能的呢?當然有啊!
先考慮同步方式的:首先最簡單的方式就是空循環消耗 CPU 時間,但不夠準確,不考慮;其次就是大多數語言都有的 Sleep。讓它睡一段時間不做事,這就不是延遲嗎?
題主說「都沒有」,那就已經錯了!但是根據題主的描述和別的一些答案的評論,顯然要的不是同步,而是非同步的:首先是 Web 前端很熟悉的 JS 的 WindowOrWorkerGlobalScope.setTimeout();其次是 C#/VB.Net 的 Task.Delay Method 。明明就有的,怎麼就沒有呢?
好了,列舉這些就夠了。結合描述說的「用 Timer 解決問題」,題主所求的不就是使用非同步方式的延遲嗎!
C#: await Task.Delay(300);
即使Visual Basic也是有的
.NET在System.Threading裡面提供了這個函數,並且是從.NET Framework 1.1開始就明確支持的
Public Shared Sub Sleep (
millisecondsTimeout As Integer
)
所以先問是不是,再問為什麼,自己不知道不等於人家沒有。你所說的所有的這些語言全都有類似功能的函數
====
PS:已編輯問題進行訂正
.net中的 Task.Delay 是非同步的,不會阻塞當前線程。
high-resolution sleep - Linux man page
高精度時鐘從來都是個大坑,基本都是系統相關的。
Arduino的編程語言就是C++,只不過重寫了一套專門給Arduino用的標準庫和編譯器而已
其它的語言,你沒有引入包含delay/sleep的庫,當然就沒法用
其實你可以使用循環 __asm ("nop") (GCC)或者 asm { nop } (VC)來達到delay相同的效果。(部分單片機內部其實就是這樣實現的)
不過呢,單片機上的程序寫出來之後不會在其他型號的單片機上運行,CPU時鐘頻率大多數情況下是能夠確定的,所以可以用這樣的方法來進行準確的等待時間,從而能夠準確獲取一些匯流排協議上的數據。
但電腦就不一樣了,你一個程序可能不只要在一台電腦上運行,時鐘頻率不僅在不同的電腦上相差很大,甚至在同一台電腦CPU滿負荷工作和比較空閑的時候時鐘頻率都相差很多。這時候,這種delay就失去了意義。
話說,你讓編程語言怎麼提供延時函數?
編譯器或解釋器,面對的就是一堆源代碼,用文本文件寫的。你根本沒告訴它硬體跑多快,也沒告訴它定時器在哪裡怎麼操作,它怎麼可能有時間的概念?
而sleep之類的函數是什麼?那是操作系統API針對編程語言做的封裝,本質是操作系統功能的延伸。操作系統是有時間概念的,所以sleep也有時間概念。
另外,sleep可不是一般意義的延時函數,而是線程的睡眠函數。當成延時函數用,也許可以,不過時間往往不準。你想睡5秒,操作系統能保證的是,5秒內不叫醒你;但操作系統一般沒法保證的是,剛好5秒的時刻非得叫醒你。也就是說,你可能會睡更長的時間。要是有高優先順序的任務一直在忙,那說不定,你眼睛一閉,就不睜了,這輩子就過去了。
首先,任何語言都能實現delay。其次,幾乎任何語言里delay都不是語言的一部分,最多是標準庫的函數之一。
然後嘛,使用空循環來精確delay有兩個條件,一是已知CPU頻率而且頻率固定,二是程序能完全控制CPU資源。否則的話一般都是用CPU中斷來計時從而實現delay的(以windows為例,每個CPU中斷windows會給每個句柄發一個計時信號,可以利用那個來delay。如果是.net環境可以Thread.Sleep,至於會卡整個程序的問題,請非同步執行函數。(有async有new Thread,就不要再抱怨多線程麻煩了,即使是C++也有多線程庫的)以前自己寫delay函數,通過循環次數模擬,根據cpu頻率,指令周期預估。那時候cpu沒有rdtsc指令,時鐘中斷是每秒18.5次,無論是cpu,還是操作系統,都無法提供毫秒級別的時間,更別說微秒。那時候io操作都要delay下,cpu更新換代,delay就不準了。那時候大部分編程語言都已經面世了。當然,delay一般用於io編程,普通編程用sleep就好了。一般是秒級別,部分語言是毫秒。
我也是做嵌入式的,我想問一下,延時函數和編程語言有什麼關係嗎?。。。
delay和語言沒有關係,它是庫函數。具體是否支持以及如何支持要取決於你的系統,以及是否有人幫你實現了支持delay的庫。delay的功能或者實現方式依然取決於你的系統,是否有操作系統?是否支持進程?是否有用戶態?是否有相關的系統調用?是否支持timer?...
目前很多語言都是支持圖形界面的,大家都知道在圖形界面時如果delay主線程那麼後果就是程序失去響應,這是一種非常惡劣的體驗,所以幾乎不會有語言提供delay這種關鍵詞或語法糖。
如果你想delay,其實也就是說線程的sleep操作,是可以通過線程庫中的sleep函數來執行,一旦你引入線程庫,那麼代表著你知道什麼是線程,那麼你也應該知道不應該去sleep主線程,這其實有點像簽訂一個協議,你在使用sleep操作前你必須深知sleep函數的優缺點並且經過深思熟慮後才使用。
另外其實用timer理論上應該是推薦的做法,timer在底層會自動幫你開闢一條專用線程(也可能是線程池或調度器)並且在任務完成後殺死或回收線程,timer還支持周期性調用、參數傳遞等、應該是理想的操作方式。對於有操作系統的開發來說,延時是系統功能。手動強制軟延時是不對的。
對於無操作系統的裸機開發來說,延時函數是和硬體體系相關的,語言也沒辦法提供標準的延時函數所以,自己的事情自己做,不要都推給編程語言看得出題主在編程方面是新手,給個指導意見吧!
語言只實現最基礎最核心的幾條邏輯,剩下的就是庫和你要做的了!
延時這個功能,是庫提供的。如果你以後想在某門語言下找某個函數,可以搜搜有沒有相關的庫,或者運行的平台有沒有相應的api,而不是想語言本身有沒有。
delay作用就是延時嘛,然後看看c怎麼延時呀,或者看看樹莓派的系統linux有沒有提供延時相關api啊!
還有,基礎課看起來是沒用,但都是內功,不可忽視。delay 這種系統級的功能,當然要放到系統的API裡面,而不是放到語言的標準庫裡面。
windows和linux都有sleep功能的函數;大多數RTOS裡面有taskDelay這種功能的系統API;Arduino雖然可以裸奔不上系統,但是你用的delay函數也是供應商做的固件庫一類的東西裡面的,肯定不是標準庫。
http://VB.net有 System.Threading.Thread.Sleep()方法
自己做編程教育的
我曾說過,ee和cs在國內的鴻溝比大家想像的大的多業內如此,行業外看過來更是如此題主是個新手
簡單來說,arduino和列舉那些「語言」的重要區別在於單片機編程大都為實時性系統。不存在大量的資源調度和任務管理,如果不能理解這層,就算跟你說了其他框架的delay可能還是知識點上有極大的偏差。還有就是大家都說的,你沒分清語言、框架、系統和編程工具這些區別
學習這些任重道遠,千萬別被現在計算機教育界浮躁的表象迷惑了
推薦閱讀:
※總是糾結於編程語言標準怎麼辦?
※用易語言寫過的最大的項目是什麼?
※編寫一個小windows桌面程序用什麼語言和工具?
※當我們在學習一門編程語言的時候,我們究竟在學習什麼?
※寫一個具有model based design功能的Simulink需要哪些技術?難度如何?