延時方法及其定時精度分析

來源:互聯網
上載者:User
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 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要好一些 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.