![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
возвращаясь к задержкам ... [D6, Win95/98, WinXP]
Vallos © (2005-07-05 16:08:00)Возникла необходимость устанавливать задержку выполнения программы (и менее 1 мс). Вроде бы и хорошая реализация:
procedure Delay_(ms: double);
var
x1, x2, freq: Int64;
begin
QueryPerformanceFrequency(freq);
QueryPerformanceCounter(x1);
repeat
QueryPerformanceCounter(x2)
until (x2-x1 >= 0.001*ms*freq);
end;
Все четко и красиво работает (от мкс до с), единственное - когда все процессы на машине заморожены: стоит повести мышкой - четкость и красота пропадает ... RDTSC работает аналогичным образом ...
Вопрос в следующем: есть ли другие реализации без привязки к частоте процика (частота которого плавает и в 'спящем режиме') или чегото ещё...
Vallos (2005-07-06 11:37:00) [21]... не пробовал ... Потому что все равно больше 1 мс с дискретностью 1 мс ...
Испробовал вот что:
procedure
var
t1, t2: TDateTime;
begin
t1:= Now;
repeat
// простое действие;
t2:= Now-t1;
until t2 >= 0.000001157407407; // 0.1 с
Label1.Caption:= FloatToStr(t2/0.0000115740740740740741)
- результат в Label1 был от 0,1089997 до 0,1100006...
'простое действие' можно исключить, результат тотже. Можно ли как-то процес ускорить (делать не через Now).
Интересная деталь: код
t1:= Now;
for i:= 1 to 50000 do t2:= Now-t1;
Label2.Caption:= FloatToStr(t2/0.000011574074074074074074074)
дает результаты от 0,01500004 до 0,01600021.
Минимальное значение i, при котором еще не 0 - 32000, но и значения такие же, как и при 60000, при 65000 и выше знечение увеличивается в 2 раза ...
А как использовать таймер 8253 (или какой там стоит)?
Vallos (2005-07-05 18:24:00) [22]Испробую завтра timeGetTime и иже с ними, результат сообщу...
Железная реализация хороша, но требует дополнительные узлы, которые можно было бы реализовать программно ...
alpet (2005-07-05 18:19:00) [23]Vallos (05.07.05 18:09) [10]
В этом случае гарантий точности никаких, но вместе с тем высокоприоритетный поток имеет большие шансы на отработку с данным интервалом (1мс), хотя раз уж работа идет с железом - синхронизировать лучше с железом. Опять же - изучайте мультимедийные таймеры высокого разрешения - это одина из немногих возможностей задавать такую небольшую задержку. Про sleep лучше вообще забыть, эта функция не дает требуемой точности.
Vallos (2005-07-05 18:09:00) [24]> 2Ботвин Дмитрий: я не утверждаю, что там 1.000 мс, просто стабильно держит (смотрем спецпримочками своей реализации на осциллографе, если это интересно)...
Перебраться на другую ось проблематично, желательни иметь привязку к 'народной' ...
А слип в делфях реализуется как
{$IFDEF MSWINDOWS}
procedure Sleep; external kernel32 name 'Sleep'; stdcall;
{$ENDIF}
{$IFDEF LINUX}
procedure Sleep(milliseconds: Cardinal);
begin
usleep(milliseconds * 1000); // usleep is in microseconds
end;
{$ENDIF}
как видно, альтернатива usleep - kernel32...
Игорь Шевченко (2005-07-05 18:05:00) [25]
> Если важна точность
Ее надо реализовать аппаратно.
alpet (2005-07-05 17:43:00) [26]Если важна точность - придется перебираться на другую ось, например Qnx или Dos. Под Windows нет возможности работать с оборудованием в режиме реального времени.
Ботвин Дмитрий (2005-07-05 17:05:00) [27]А ты что замерял чем-то этот интервал? С чего ты взял, что
Sleep обеспечивает задержку в 1мс? Если передал ей такой параметр, это не значит, что твой поток замер ровно на 1мс. Если в этот момент времени появился в списке планируемых потоков поток
с более высоким приоритетом, то планировщик потоков именно ему
выделит квант процессорного времени, а твой продолжит работать тока после него и реальная задержка может оказаться гараздо больше чем 1мс....
Digitman (2005-07-05 17:03:00) [28]
> Vallos (05.07.05 17:00) [5]
> для работы с внешними устройствами
для работы с периферией, требующей такую временную дискретность и прецизионность Win32 никаким боком не подходит - нужна риэл-тайм опер.система, хоть тот же ДОС
Vallos (2005-07-05 17:00:00) [29]... согласен, что QueryPerformanceCounter не катит, а что катит?
> 2 Digitman: для работы с внешними устройствами...
2All: кстати, sleep(x) вполне корректно спавляется с поставленной задачей, правда только от 1 мс, с дискретностью 1 ...
Ботвин Дмитрий (2005-07-05 16:48:00) [30]Кстати, такие задержки с помощью QueryPerformanceFrequency
и QueryPerformanceCounter не реализовать. Они принимают допущения, что твой поток не вытесняется более приоритетными, а
работает не прерывно. Поэтому движения мышкой и нарушают всю красоту, как ты говоришь. Этот поток и куча других, более приоритетных, будут вносить погрешности...
Ботвин Дмитрий (2005-07-05 16:44:00) [31]А-га, и причём в среде с вытесняющей многозадачностью, где
каждому потоку тока по 20мс, примерно, отводится процессорного
времени :-)))
Digitman (2005-07-05 16:30:00) [32]
> Vallos
> менее 1 мс
а можно полюбопытствовать, за каким лядом такая дискретность понадобилась в мультизадачной(а не риэл-тайм) среде ?
alpet (2005-07-05 16:24:00) [33]Тебе вероятно нужно изучить мультимедийные таймеры - они позволяют оперировать такими задержками.
functions:
timeBeginPeriod
timeEndPeriod
timeGetDevCaps
timeGetSystemTime
timeGetTime
timeKillEvent
TimeProc
timeSetEvent