zoukankan      html  css  js  c++  java
  • Delphi中三种延时方法及其定时精度分析

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

    来自:lili_0522 时间:2005-7-14 16:21:05  
     在Delphi中,通常可以用以下三种方法来实现程序的延时,即TTtimer控件,Sleep函数,GetTickCount函数。但是其精度是各不相同的。
    一、三种方法的简单介绍

    1)TTtimer控件

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

    2)Sleep函数

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

    sleep(1000); //延迟1000毫秒

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

    3)GetTickCount函数

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

    procedure Delay(MSecs: Longint);
    //延时函数,MSecs单位为毫秒(千分之1秒)
    var
    FirstTickCount, Now: Longint;
    begin
    FirstTickCount := GetTickCount();
    repeat
    Application.ProcessMessages;
    Now := GetTickCount();
    until (Now - FirstTickCount >= MSecs) or (Now < FirstTickCount);
    end;

    二、高精度的微妙级性能计数器(high-resolution performance counter)介绍

      为了比较以上方法的精度,首先需要找到一个参考的定时器。在这里,我提供了两个参考的定时器。一是用单片机每隔1.024ms产生一个实时中断RTI,作为计数器;二是选用了一个高精度的微妙级性能计数器(参见: http://msdn.microsoft.com/msdnmag/issues/04/03/HighResolutionTimer/default.aspx ,或者 http://community.csdn.net/Expert/FAQ/FAQ_Index.asp?id=200249


    1)计数器的Delphi源代码

    {
    A high-precision counter/timer. Retrieves time differences
    downto microsec.
    Quick Reference:
    THPCounter inherits from TComponent.

    Key-Methods:
    Start: Starts the counter. Place this call just before the
    code you want to measure.

    Read: Reads the counter as a string. Place this call just
    after the code you want to measure.

    ReadInt: Reads the counter as an Int64. Place this call just
    after the code you want to measure.
    --------------------------------------------------------------------------------
    }
    unit HPCounter;

    interface

    uses
    SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls,
    Forms, Dialogs, StdCtrls, ExtCtrls;

    type
    TInt64 = TLargeInteger;
    THPCounter = class(TComponent)
    private
    Frequency: TLargeInteger;
    lpPerformanceCount1: TLargeInteger;
    lpPerformanceCount2: TLargeInteger;
    fAbout: string;
    procedure SetAbout(Value: string);
    { Private declarations }
    public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    procedure Start;
    function Read: string;
    function ReadInt: TLargeInteger;
    { Private declarations }
    published
    property About: string read fAbout write SetAbout;
    { Published declarations }
    end;


    procedure Register;

    implementation

    procedure Register;
    begin
    RegisterComponents('MAs Prod.', [THPCounter]);
    end;

    constructor THPCounter.Create(AOwner: TComponent);
    begin
    inherited Create(AOwner);
    fAbout:= 'Version 1.1, 2000&reg; Mats Asplund, EMail: masprod@telia.com, Site: http://go.to/masdp';
    end;

    destructor THPCounter.Destroy;
    begin
    inherited Destroy;
    end;

    function THPCounter.Read: string;
    begin
    QueryPerformanceCounter(TInt64((@lpPerformanceCount2)^));
    QueryPerformanceFrequency(TInt64((@Frequency)^));
    Result:=IntToStr(Round(1000000 * (lpPerformanceCount2 -
    lpPerformanceCount1) / Frequency));
    end;

    function THPCounter.ReadInt: TLargeInteger;
    begin
    QueryPerformanceCounter(TInt64((@lpPerformanceCount2)^));
    QueryPerformanceFrequency(TInt64((@Frequency)^));
    Result:=Round(1000000 * (lpPerformanceCount2 -
    lpPerformanceCount1) / Frequency);
    end;

    procedure THPCounter.SetAbout(Value: string);
    begin
    Exit;
    end;

    procedure THPCounter.Start;
    begin
    QueryPerformanceCounter(TInt64((@lpPerformanceCount1)^));
    end;

    end.

    2)使用方法:
    unit Unit1;

    interface

    uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    HPCounter, StdCtrls;

    type
    TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    procedure Button1Click(Sender: TObject);
    private
    { Private declarations }
    public
    { Public declarations }
    end;

    var
    Form1: TForm1;

    implementation

    {$R *.DFM}

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    Edit1.Text:= '';
    Application.ProcessMessages;
    with THPCounter.Create(Self) do
    begin
    Start;
    // Place code to measure here
    Sleep(1000);
    // Place code to measure here
    Edit1.Text:=Read;
    Free;
    end;
    end;

    end.

    二、三种方法的精度比较

      为了比较,采用以上3种方法,分别设置延时时间为1ms、2ms、5ms、10ms、20ms、50ms、100ms、200ms、500ms、1000ms,循环次数为5次,得到实际的延时时间。

    1)TTtimer控件

    实际延时时间(ms)
    1ms: 8.012 21.551 6.875 21.647 9.809
    2ms: 9.957 20.675 14.671 11.903 20.551
    5ms: 9.952 20.605 9.924 20.705 12.682
    10ms:14.852 9.96 21.547 9.82 20.634
    20ms:27.512 34.291 26.427 31.244 30.398
    50ms:61.196 61.307 64.027 62.048 63.059
    100ms:102.495 108.408 112.318 110.322 102.531
    200ms:193.955 202.135 207.016 205.082 202.194
    500ms:496.659 500.534 503.398 495.551 500.394
    1000ms:999.699 1003.576 993.698 1004.443 995.625

    2)Sleep函数

    1ms: 1.895 1.895 1.896 1.897 1.898
    2ms: 2.868 2.874 2.852 2.872 2.869
    5ms: 5.8 5.797 5.79 5.79 5.791
    10ms:10.675 10.683 10.611 10.669 10.67
    20ms:20.404 20.434 20.447 20.477 20.368
    50ms:50.67 50.691 50.69 50.682 50.671
    100ms:100.515 100.469 100.484 100.481 100.484
    200ms:200.101 200.126 199.892 200.066 200.108
    500ms:499.961 499.961 499.958 499.961 499.96
    1000ms:1000.034 1000.04 1000.03 1000.018 1000.029

    3)GetTickCount函数

    1ms: 15.54 15.596 15.527 15.566 15.838
    2ms: 15.561 15.563 15.603 15.477 15.571
    5ms: 15.519 15.549 15.569 15.666 15.394
    10ms:15.558 15.561 15.522 15.568 15.518
    20ms:31.186 31.137 31.17 31.17 31.19
    50ms:62.445 62.4 63.893 60.88 62.404
    100ms:109.276 109.298 109.273 109.28 109.28
    200ms:203.027 203.084 203.021 203.027 203.046
    500ms:499.959 499.961 499.963 499.967 499.965
    1000ms:1000.023 1000.022 1000.026 1000.029 1000.021


      可见,相对而言,Sleep的精度最高,尤其是在10ms以内的延时,只有sleep函数才能够做到。TTimer控件的定时精度最差,而且稳定性不好,波动很大。GetTickCount函数所能实现的最短延时为15ms左右,稳定性相对TTimer要好一些。
  • 相关阅读:
    基于DM642 RAW采集格式的视频驱动开发及应用
    嵌入式开发之davinci--- 8148/8168/8127 中的添加算饭scd 场景检测 代码实现
    如何在外部采用AES-128对HLS的TS流进行加密
    阶段3 2.Spring_03.Spring的 IOC 和 DI_11 set方法注入
    阶段3 2.Spring_03.Spring的 IOC 和 DI_10 构造函数注入
    阶段3 2.Spring_03.Spring的 IOC 和 DI_9 spring的依赖注入
    阶段3 2.Spring_03.Spring的 IOC 和 DI_8 spring中bean的细节之生命周期
    阶段3 2.Spring_03.Spring的 IOC 和 DI_7 spring中bean的细节之作用范围
    阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式
    阶段3 2.Spring_03.Spring的 IOC 和 DI_5 BeanFactory和ApplicationContext的区别
  • 原文地址:https://www.cnblogs.com/Bung/p/2048861.html
Copyright © 2011-2022 走看看