用Windows API編寫乙個精確定時的迴圈

2021-08-09 03:59:21 字數 1954 閱讀 6309

這幾天跟網友討論乙個程式優化問題時,遇到乙個需要延時的迴圈,結合我所知道的知識,並突發靈感,想到了用windows系統提供的定時器api寫乙個精確延時迴圈的方法。

for(int i = 0; i < maxcount;i++)

基於sleep延時的不穩定,不精確性,這個迴圈延時,效果非常的糟糕,我想到的改進辦法就是使用waitable timer核心物件來精確延時改造迴圈,因為這個核心物件可以精確定時到1ms這個量級,當然改造後,可以精確定時到100納秒這麼水平,首先我們來看看,如何改造成精確1ms一次的迴圈:

handle htimer = null;

large_integer liduetime;

liduetime.quadpart = -1;

htimer = createwaitabletimer(null, false, null);

if (null == htimer)

long lcycle = 1;  //1毫秒觸發一次

if (!setwaitabletimer(htimer, &liduetime, lcycle, null, null, 0))

int i = maxcount;

while( (i > 0) && waitforsingleobject(htimer, infinite) != wait_object_0)

像上面這樣我們就得到乙個1ms執行一次的迴圈,當然看似程式有點複雜,但是這個複雜性只是一種表面的,實際上我們得到了乙個1毫秒迴圈一次的迴圈,當然這個需要你確定你的dosomething這樣的迴圈體函式的執行時間是1毫秒以內的,否則這個延時就沒有意義了。

接著我們再來考慮如何得到乙個精確到100納秒一次的迴圈,這個就需要一點技巧了,首先我們不能再建立自動重置的計時器物件,而要改為手工,因為100納秒這個精度只有再次呼叫setwaitabletimer才能得到,所以必須要手工重置,每次都呼叫一下這個函式,重置等待100納秒,不囉嗦了,上**:  

handle htimer = null;

large_integer liduetime;

liduetime.quadpart = 1;

htimer = createwaitabletimer(null, true, null);

if (null == htimer)

if (!setwaitabletimer(htimer, &liduetime, 0, null, null, 0))

int i = maxcount;

while( (i > 0) && waitforsingleobject(htimer, infinite) != wait_object_0)

--i;

}

這段**和前段**,有些細節方面的差異,仔細看**就知道了,不再贅述。而需要提醒注意的就是,這個實際上是使每次dosomething都間隔100納秒呼叫,與前乙個迴圈邏輯上是不同的,所以這個要特別注意,當然通過把setwaitabletimer函式調整到dosomething之前,就可以得到與前乙個迴圈邏輯一致的迴圈了,這不是什麼難事,當然這個就需要你的函式一定要在100納秒以內幹完活,否則,延時就沒有什麼意義了。

最後,還是提醒下吧,liduetime本質是個64位的變數,在作為setwaitabletimer函式的引數時,它的最小時間單位就是100納秒,這樣你賦值1就表示1*100納秒,2就表示200納秒,以此類推,但是你沒法指定小數來得到1.5*100納秒這樣的數,這就是100納秒為單位的確切含義,100納秒就成了不可逾越的鴻溝。當然對於一般目的的程式來說,這足夠了。同樣的那個lcycle引數的含義也是一樣的,只是單位是1毫秒最小,無法再小了,同時第二個定時迴圈中沒有用這個引數,在這種情況下用它也是沒有什麼意義的。

至此精確延時迴圈的編寫方法就介紹完了,他可以用於不用訊息迴圈,而需要週期性操作的場合,比如週期性的傳送乙個資料報,週期性的輪詢乙個裝置的狀態等。

用Objective C編寫乙個終端應用

在main函式中,必須建立乙個autorelease pool,objective c用它來管理記憶體。編譯 用的是clang命令,它的一些選項有 fobjc objective c是使用的程式語言 arc automatic reference counting framework 鏈結到foun...

用python編寫乙個小遊戲

1.隨機生成兩個數字 1 1000 在控制台中隨機獲取兩個數字相加 如果使用者輸入正確得10分,否則扣10分。總共5道題,最後輸出得分 import random grade 0for i in range 5 num1 random.randint 1,100 num2 random.randin...

用AJAX編寫乙個簡單的相簿

xml問題終於在今天還是解決了。最後在firefox裡還是使用了dom的一些老方法。我這裡就具體解釋一下方法吧.var xmlhttp 用來定義乙個xmlhttprequest物件 上面這段話是判斷當前瀏覽器版本,以定義給xmlhttp不同的xmlhttprequest物件.如果伺服器的響應沒有xm...