其他语言

位置:IT落伍者 >> 其他语言 >> 浏览文章

Delphi中三种延时方法及其定时精度分析


发布日期:2021年08月22日
 
Delphi中三种延时方法及其定时精度分析
在Delphi中通常可以用以下三种方法来实现程序的延时即TTtimer控件Sleep函数GetTickCount函数但是其精度是各不相同的

三种方法的简单介绍

)TTtimer控件

TTtimer控件的实质是调用Windows API定时函数SetTimer和KillTimer来实现的并简化了对WM_TIMER 消息的处理过程通过设置OnTimer事件和Interval属性我们可以很方便的产生一些简单的定时事件

)Sleep函数

Sleep函数用来使程序的执行延时给定的时间值Sleep的调用形式为Sleep(milliseconds)暂停当前的进程milliseconds毫秒Sleep的实现方法其实也是调用Windows API的Sleep函数例如

sleep();//延迟毫秒

Sleep会引起程序停滞如果你延迟的时间较长的话你的程序将不能够响应延时期间的发生的其他消息所以程序看起来好像暂时死机

)GetTickCount函数

在主程序中延时为了达到延时和响应消息这两个目的GetTickCount()构成的循环就是一种广为流传的方法例如

procedure Delay(MSecs: Longint);

//延时函数MSecs单位为毫秒(千分之秒)

var

FirstTickCount Now: Longint;

begin

FirstTickCount := GetTickCount();

repeat

ApplicationProcessMessages;

Now := GetTickCount();

until (Now FirstTickCount >= MSecs) or (Now < FirstTickCount);

end;

高精度的微妙级性能计数器(highresolution performance counter)介绍

为了比较以上方法的精度首先需要找到一个参考的定时器在这里我提供了两个参考的定时器一是用单片机每隔ms产生一个实时中断RTI作为计数器二是选用了一个高精度的微妙级性能计数器(参见 ltaspx 或者

)计数器的Delphi源代码

{

Ahighprecisioncounter/timerRetrievestimedifferences

downtomicrosec

QuickReference:

THPCounterinheritsfromTComponent

KeyMethods:

Start:StartsthecounterPlacethiscalljustbeforethe

codeyouwanttomeasure

Read:ReadsthecounterasastringPlacethiscalljust

afterthecodeyouwanttomeasure

ReadInt:ReadsthecounterasanIntPlacethiscalljust

afterthecodeyouwanttomeasure

}

unitHPCounter;

interface

uses

SysUtilsWinTypesWinProcsMessagesClassesGraphicsControls

FormsDialogsStdCtrlsExtCtrls;

type

TInt=TLargeInteger;

THPCounter=class(TComponent)

private

Frequency:TLargeInteger;

lpPerformanceCount:TLargeInteger;

lpPerformanceCount:TLargeInteger;

fAbout:string;

procedureSetAbout(Value:string);

{Privatedeclarations}

public

constructorCreate(AOwner:TComponent);override;

destructorDestroy;override;

procedureStart;

functionRead:string;

functionReadInt:TLargeInteger;

{Privatedeclarations}

published

propertyAbout:stringreadfAboutwriteSetAbout;

{Publisheddeclarations}

end;

procedureRegister;

implementation

procedureRegister;

begin

RegisterComponents(MAsProd[THPCounter]);

end;

constructorTHPCounterCreate(AOwner:TComponent);

begin

inheritedCreate(AOwner);

fAbout:=Version®MatsAsplundEMail:Site:;

end;

destructorTHPCounterDestroy;

begin

inheritedDestroy;

end;

functionTHPCounterRead:string;

begin

QueryPerformanceCounter(TInt((@lpPerformanceCount)^));

QueryPerformanceFrequency(TInt((@Frequency)^));

Result:=IntToStr(Round(*(lpPerformanceCount

lpPerformanceCount)/Frequency));

end;

functionTHPCounterReadInt:TLargeInteger;

begin

QueryPerformanceCounter(TInt((@lpPerformanceCount)^));

QueryPerformanceFrequency(TInt((@Frequency)^));

Result:=Round(*(lpPerformanceCount

lpPerformanceCount)/Frequency);

end;

procedureTHPCounterSetAbout(Value:string);

begin

Exit;

end;

procedureTHPCounterStart;

begin

QueryPerformanceCounter(TInt((@lpPerformanceCount)^));

end;

end

)使用方法

unitUnit;

interface

uses

WindowsMessagesSysUtilsClassesGraphicsControlsFormsDialogs

HPCounterStdCtrls;

type

TForm=class(TForm)

Button:TButton;

Edit:TEdit;

Label:TLabel;

Label:TLabel;

procedureButtonClick(Sender:TObject);

private

{Privatedeclarations}

public

{Publicdeclarations}

end;

var

Form:TForm;

implementation

{$R*DFM}

procedureTFormButtonClick(Sender:TObject);

begin

EditText:=;

ApplicationProcessMessages;

withTHPCounterCreate(Self)do

begin

Start;

//Placecodetomeasurehere

Sleep();

//Placecodetomeasurehere

EditText:=Read;

Free;

end;

end;

end

三种方法的精度比较

为了比较采用以上种方法分别设置延时时间为msmsmsmsmsmsmsmsmsms循环次数为得到实际的延时时间

)TTtimer控件

实际延时时间(ms)

ms

ms

ms

ms

ms

ms

ms

ms

ms

ms

)Sleep函数

ms

ms

ms

ms

ms

ms

ms

ms

ms

ms

)GetTickCount函数

ms

ms

ms

ms

ms

ms

ms

ms

ms

ms

可见相对而言Sleep的精度最高尤其是在ms以内的延时只有sleep函数才能够做到TTimer控件的定时精度最差而且稳定性不好波动很大GetTickCount函数所能实现的最短延时为ms左右稳定性相对TTimer要好一些               

上一篇:Delphi中ScriptControl的高级应用

下一篇:Delphi中包的妙用