在Windows中的很多場合下編程(例如工業控制游戲)中需要比較精確的記時器本文討論的是在Delphi下實現記時器的若干方法以及它們的精度控制問題
在Delphi中最常用的是Timer控件它的設置和使用都非常方便理論上它的記時精度可以達到ms(毫秒)但是眾所周知的實際上Timer在記時間隔小於ms之下是精度是十分差的它只適用於對於精度要求不太高的場合
這裡作者要介紹的是兩種利用Windows API函數實現精確記時的方法第一中方法是利用高性能頻率記數(作者本人的稱呼)法利用這種方法要使用兩個API函數QueryPerformanceFrequency和QueryPerformanceCounterQueryPerformanceFrequency函數獲得高性能頻率記數器的震蕩頻率
調用該函數後函數會將系統頻率記數器的震蕩頻率(每毫秒)保存到一個LargeInteger中不過利用該函數在幾台機器上做過試驗結果都是讀者朋友可以在自己的機器上試一下
QueryPerformanceCounter函數獲得系統頻率記數器的震蕩次數結果也保存到一個Largenteger中
很顯然如果在計時中首先使用QueryPerformanceFrequency獲得高性能頻率記數器每毫秒的震蕩次數然後在計時開始時使用QueryPerformanceCounter函數獲得當前系統頻率記數器的震蕩次數在計時結束時再調用QueryPerformanceCounter函數獲得系統頻率記數器的震蕩次數將兩者相減再將結果除以頻率記數器每毫秒的震蕩次數就可以獲得某一事件經過的准確時間(次數除以頻率等於時間)
另外的一種精確記時器的功能是利用多媒體記時器函數(這也是作者的定義因為這個系列的函數是在Winmmdll中定義並且是為媒體播放服務的)
實現多媒體記時器首先要使用timeSetEvent函數建立計時事件該函數在Delphi中的mmsystempas中有定義定義如下
function timeSetEvent(uDelay uResolution: UINT;
lpFunction: TFNTimeCallBack; dwUser: DWORD; uFlags: UINT): MMRESULT; stdcall
函數定義中參數uDelay定義延遲時間以毫秒為單位該參數相當於Timer控件的Interval屬性參數uResolution定義記時精度如果要求盡可能高的精度要將該參數設置為參數lpFunction定義了timeSetEvent函數的回調函數該函數相當於一個定時中斷處理函數每當經過一個uDelay長度的時間間隔該函數就會被調用編程者可以在該函數中加入相應的處理語句參數dwUser定義用戶自定義的回調值該值將傳遞給回調函數參數uFlags定義定時類型如果要不間斷的記時該值應設置為
如果函數調用成功在系統中建立了一個多媒體記時器對象每當經過一個uDelay時間後lpFunction指定的函數都會被調用同時函數返回一個對象標識如果不再需要記時器則必須要使用timeKillEvent函數刪除記時器對象
由於Windows是一個多任務的操作系統因此基於API調用的記時器的精度都會受到其它很多因素的干擾到底這兩中記時器的精度如何我們來使用以下的程序進行驗證
設置三種記時器(Timer控件高性能頻率記數多媒體記時器)將它們的定時間隔設置為毫秒讓它們不停工作直到達到一個比較長的時間(比如秒)這樣記時器的誤差會被累計下來然後同實際經過的時間相比較就可以得到它們的精度
[] [] [] []
From:http://tw.wingwit.com/Article/program/Delphi/201311/25026.html