不同編程語言的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 & using namespace std::chrono_literals;
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需要哪些技術?難度如何?

TAG:編程語言 | 編程 | 單片機 |