翰文个人计算机学习网
  • 翰文快讯
  • 翰文PC快讯
  • 综合软件区
  • 操作系统
  • 注册表解析
  • Windows系列
  • Unix/Linux
  • 其他系统
  • 应用软件
  • 微软MS Office
  • WPS Office
  • 多媒体软件
  • 图像处理
  • Photoshop
  • Painter
  • Illustrator
  • CorelDRAW
  • 三维空间
  • AutoCAD
  • 3DMAX
  • 3DMAYA
  • 硬件资源
  • 攒机指南
  • 硬件超频
  • 维修指南
  • 网络资源
  • 在线通讯
  • 网上冲浪
  • 浏览器中心
  • 网络故障解析
  • 病毒资料
  • 病毒通报
  • 病毒防治
  • 病毒常识
  • 黑客技巧
  • SQL/MySQL
  • Oracle
  • Delphi
  • 编程资源
  •  C/C#/C++/VC++/VC.NET
  •  Basic/VB/VB.NET/VBScript
  •  FoxBasic/FoxPro/VF/VF.NET
  •  Java/JavaScript
  • PowerBuilder
  • 热门词:
  • 翰文计算机学习网首页
  • >
  • Delphi
  • >
  • Delphi中三种延时方法及其定时精度分析
  • Delphi中三种延时方法及其定时精度分析

  • 资源来源:
  • HW-PCS.ORG
  • 资源作者:
  • 翰文计算机学习网
  • 人气指数:
  • [5041]
  • 关键词:Windows
      在 Delphi 中,通常可以用以下三种方法来实现程序的延时,即TTtimer 控件,Sleep 函数,GetTickCount 函数。但是其精度是各不相同的。

      一、三种方法的简单介绍

      1)TTtimer控件

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

      2)Sleep函数

      Sleep函数用来使程序的执行延时给定的时间值。Sleep的调用形式为Sleep(milliseconds),暂停当前的进程milliseconds毫秒。Sleep的实现方法其实也是调用 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® 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
        , 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要好一些。

    感谢您对翰文计算机学习网的支持

  • 关于我们
  • 联系方式
  • 成功案例
  • 技术报价
  • RSS索引
  • 网站地图
  • 翰文电脑学习网
  • MSN:LNDDYGYC9@HOTMAIL.COM Powered by 翰文个人计算机学习网 版权所有,未经允许不得转载
    ICP备案号码:[沪ICP备12020678号] Copyright 2008-2020 HW-PCS.ORG, All Rights Reserved.