Code:

procedure Delay(dwMilliseconds: Longint);

var

iStart, iStop: DWORD;

begin

iStart := GetTickCount;

repeat

iStop := GetTickCount;

Application.ProcessMessages;

until (iStop - iStart) >= dwMilliseconds;

end;

 

Взято с сайта: https://www.swissdelphicenter

 

 

Примечание от Vit: функция будет "безбожно" жрать процессорное время. Если ожидаемые интервалы задержек достаточно велики, то очень желательно её дополнить следующим образом:

 

Code:

procedure Delay(dwMilliseconds: Longint);

{©Drkb v.3(2007): www.drkb, 

®Vit (Vitaly Nevzorov) - nevzorov}

var

iStart, iStop: DWORD;

begin

iStart := GetTickCount;

repeat

iStop := GetTickCount;

sleep(10);

Application.ProcessMessages;

until (iStop - iStart) >= dwMilliseconds;

end;

 

Команда Sleep будет отдавать время другим приложением, но точность отмеряемого интервала пострадает на 0.01 секунды, что сопоставимо с общей погрешностью предложенного метода.

 


 

Code:

procedure Delay(msecs: Longint);

var

targettime: Longint;

Msg: TMsg;

begin

targettime := GetTickCount + msecs;

while targettime > GetTickCount do

if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then

begin

If Msg.message = WM_QUIT Then

begin

PostQuitMessage(msg.wparam);

Break;

end;

TranslateMessage(Msg);

DispatchMessage(Msg);

end;

end;

 

{

Note:

The elapsed time is stored as a DWORD value.

Therefore, the time will wrap around to zero if the system is

run continuously for 49.7 days.

}

 

Взято с сайта: https://www.swissdelphicenter.ch

 

 


 

Code:

{

The Sleep function suspends the execution of the current

thread for a specified interval.

}

 

Sleep(dwMilliseconds: Word);

 

 

Взято с сайта: https://www.swissdelphicenter

 

 

Примечание от Vit: эта функция страдает многими недостатками, во-первых ни о какой точности речь и не идёт, погрешности среднепотолочные, во-вторых при количестве милисекунд большем 100 функция будет создавать эффект "подвисания" приложения, так как во время её работы приложение не будет отвечать на внешние воздействия. Собственно сама по себе функция sleep вовсе не для отсчёта времени и не для задержки на определённый интервал, её назначение в другом - отдать процессорное время в течение заданного интервала другим процессам. Код можно подправить примерно таким образом:

Code:

Procedure Delay (IntervalinSeconds:integer);

var i:integer;

{©Drkb v.3(2007): www.drkb, 

®Vit (Vitaly Nevzorov) - nevzorov}

begin

For i:=0to IntervalinSeconds*100do

begin

sleep(10);

Application.ProcessMessages;

end;

end;

Это "поправит" подвисание, но не улучшит точность. Эта функция хороша для задержек на период от секунд до несколько минут когда точность не важна.

 

Можно так же помудрив сделать и возможность прерывания ожидания по нажатию кнопки, примерно так:

 

Code:

var Canceled:boolean; // должна быть объявлена как глобальная переменная модуля

 

.....

Function Delay (IntervalinSeconds:integer):boolean; //возвращает true если отработала не прерываясь

{©Drkb v.3(2007): www.drkb, 

(Vitaly Nevzorov) - Этот адрес электронной почты защищён от спам-ботов. У вас должен быть включен JavaScript для просмотра.}var i:integer;

begin

Canceled:=false;

For i:=0to IntervalinSeconds*100do

begin

sleep(10);

Application.ProcessMessages;

if Canceled then break;

end;

Result:=not Canceled;

end;

 

........

 

Procedure TForm1.onButton1Click(Sender:TObject);

begin

Canceled:=true;

end;

 

 

 


 

Code:

{

Including the Sleep in the loop prevents the app from hogging

100% of the CPU for doing practically nothing but running around the loop.

}

 

procedure PauseFunc(delay: DWORD);

var

lTicks: DWORD;

begin

lTicks := GetTickCount + delay;

repeat

Sleep(100);

Application.ProcessMessages;

until (lTicks <= GetTickCount) or Application.Terminated;

end;

 

 

 

Взято с сайта: https://www.swissdelphicenter.ch

 

 


 

Code:

procedure Delay(Milliseconds: Integer);

{by Hagen Reddmann}

var

Tick: DWord;

Event: THandle;

begin

Event := CreateEvent(nil, False, False, nil);

try

Tick := GetTickCount + DWord(Milliseconds);

while (Milliseconds > 0) and

(MsgWaitForMultipleObjects(1, Event, False, Milliseconds, QS_ALLINPUT) <> WAIT_TIMEOUT) do

begin

Application.ProcessMessages;

Milliseconds := Tick - GetTickcount;

end;

finally

CloseHandle(Event);

end;

end;

 

 

Взято с сайта: https://www.swissdelphicenter

Данная тема уже обсуждалась, но у меня есть своя реализация сабжа. Начиная с Pentium MMX, Intel ввели в процессор счетчик тактов на 64 бита (Присутствует точно и в К6). Для того чтобы посмотреть на его содержание, была введена команда "rdtsc" (подробное описание в интеловской мануале). Эту возможность можно использовать для реализации сабжа.

Поскольку Дельфи не в курсе насчет rdtsc, то пришлось юзать опкод (0F31).

Привожу простенький примерчик юзания, Вы уж извините - немножко кривоват получился, да и ошибка компилятора какая-то вылезла :( (V4 Bld5.104 Upd 2). Кому интересно, поделитесь своими соображениями по этому поводу. Особенно интересует работа в режиме когда меняется частота процессора (Duty Cycle, Standby).

 

Code:

// (C) 1999 ISV

unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms,Dialogs, StdCtrls, Buttons, ExtCtrls;

type TForm1 = class(TForm)

Label1: TLabel;

Timer1: TTimer;

Label2: TLabel;

Label3: TLabel;

Button1: TButton;

Button2: TButton;

Label4: TLabel;

procedure Timer1Timer(Sender: TObject);

procedure FormActivate(Sender: TObject);

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

Counter:integer;

//Счетчик срабатывания таймера

Start:int64;

//Начало роботы

Previous:int64;

//Предыдущее значение

PStart,PStop:int64;

//Для примера выч. времени

CurRate:integer;

//Текущая частота проца

function GetCPUClick:int64;

function GetTime(Start,Stop:int64):double;

end;

var Form1: TForm1;implementation{$R *.DFM}

// Функция работает на пнях ММХ или выше а

// также проверялась на К6

function TForm1.GetCPUClick:int64;

begin

asm db 0fh,31h

// Опкод для команды rdtsc mov dword ptr result,eax mov dword ptr result[4],edx

end;

// Не смешно :(. Без ?той штуки

// Компайлер выдает Internal error C1079

Result:=Result;

end;

// Время в секундах между старт и стоп

function TForm1.GetTime(Start,Stop:int64):double;

begin

try result:=(Stop-Start)/CurRate except result:=0;

end;

end;

// Обработчик таймера считает текущую частоту, выводит ее, а также

// усредненную частоту, текущий такт с момента старта процессора.

// При постоянной частоте процессора желательно интервал братьпобольше

// 1-5с для точного прощета частоты процессора.

procedure TForm1.Timer1Timer(Sender: TObject);

var i:int64;

begin

i:=GetCPUClick;

if Counter=0then Start:=i else

begin

Label2.Caption:=Format('Частота общая:%2f',[(i-Start)/(Counter*Timer1.Interval*1000)]);

Label3.Caption:=Format('Частота текущая:%2f',[(i-Previous)/(Timer1.Interval*1000)]);

CurRate:=Round(((i-Previous)*1000)/(Timer1.Interval));

end;

Label1.Cap примера

procedure TForm1.Button1Click(Sender: TObject);

begin

PStart:=GetCPUClick;

end;

// Останавливаем отсчет времени и показуем соко

// прошло секунд

procedure TForm1.Button2Click(Sender: TObject);

begin

PStop:=GetCPUClick;

Label4.Caption:=Format!

('Время между нажатиями:%gсек',[GetTime(PStart,PStop)])

end;

end.