Консультация № 159463
03.02.2009, 08:11
0.00 руб.
0 7 0
Здравствуйте Уважаемые Эксперты!
Подскажите как в Дельфи сделать задержку меньше 1 мсек (это минимум по стандартному таймеру), при этом программа не должна зависать на время задержки, то есть реагировать на мышку, клавиатуру, выполнять какую-нибудь другую процедуру.
За ранее благодарю за ответ.

Обсуждение

Неизвестный
03.02.2009, 09:03
общий
Теоритически можно использовать переменную Time сравнивая разницу между старым значением и новым. Для получения секунд необходимо умножить на (24*60*60) = 86400
Для того чтоб программа не висла, необходимо использовать application.processmesage - метод обработает все поступившие сообщения.
Но мне кажется столь короткие промежутки времени, с хорошей точностью, отловить нереально. Опишите задачу полнее, возможно решение есть.
давно
Мастер-Эксперт
425
4118
03.02.2009, 09:27
общий
Ну, если и мультимедиа-таймер Вам не нравится, то других таймеров нет. Тогда Вам нужно использовать две функции GetTickCount и сравнивать разницу между результатами с необходимым Вам параметром. Оформляете эту штуку в виде отдельной процедуры и запускаете эту процедуру в отдельном потоке, чтобы она не вешала основную программу и ход выполнения основной программы не сильно влиял на отсчёт.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
давно
Академик
20764
1861
03.02.2009, 10:46
общий
Задержка без зависания - это работа с прерываниями. Увеличить частоту системного таймера вряд ли можно безнаказанно. Но можно использовать периодические прерывания от rtc (если конечно его не использует сама ОС. Linux не использует).
Только это к delphi имеет весьма опосредованное отношение.
Неизвестный
04.02.2009, 10:46
общий
Есть способ как засечь более мелкие промежутки времени чем 1 мсек (через тики процессора (команда ассемблера rdtsc) и знание частоты CPU), но таким образом точную задержку не организовать. Хотя попытаться организовать поток с постоянным анализом тиков и генерацией событий по более мелким промежуткам времени можно, но скорее всего такой поток будет сильно грузить процессор (точнее - одно ядро, если очень надо можно и пожертвовать этим). Но действительно ли надо?

По поводу GetTickCount : [MSDN] GetTickCount function retrieves the number of milliseconds that have elapsed since the system was started. It is limited to the resolution of the system timer. Т.е. меньше мсек с помощью ее все равно не получить.
давно
Мастер-Эксперт
425
4118
04.02.2009, 13:32
общий
PavelGM
Многое будет зависеть от функции, которая выполняется при срабатывании таймера. Системный таймер, если не успевает выполнить функцуию в течении своей разрешающей способности (примерно 15 мс или около того), будет устойчиво накапливать ошибку, если функция каждый раз не будет создавать для себя отдельный поток. Точнее, функция должна быть уже сама по себе в отдельном потоке.
Мультимедиатаймер, судя по MSDN, вызывает свою callback-функцию уже в отдельном потоке, но и здесь, как ни странно, бывают ошибки периода при разрешении менее чем в 2..3 мс.
А вот с GetTickCount можно задать создание нового потока при каждом наступлении новой милисекунды, если старый отдельный поток не успел отработать и, тем самым, гарантировать разрешающую способность в 1 мс. Впрочем, тут нужны эксперименты.
Таким образом всё упирается в решаемую функцией таймера задачи.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
05.02.2009, 00:47
общий
To sir Henry
В вопросе спрашивалось можно ли "сделать задержку меньше 1 мсек". Замечание по поводу GetTickCount касается именно этого. Cобственно единственный известный мне метод как можно это попытаться (!) сделать это - использовать команду rdtsc.
Неизвестный
08.02.2009, 13:36
общий
Всё просто, если у Вас не ОС реального времени, (а вопрос по Delphi, следовательно у Вас Windows – это не операционка реального времени), то Вы не теоретически не практически не сможете реализовать такой опрос/задержку. Максимум что Вы сможете гарантировать на 100% - это 0,5 секунды. Всё что ниже (например, 100 мсек) – это на усмотрение ОС, т.е. может сейчас и будет выдержан такой период, но в следующий момент никто Вам не даст гарантии что задержка не составит 800 мсек.. Даже великий Бил Гейтс тут не поможет.
Эта проблема довольно распространена, и весьма часты заключения и даже «гарантии» знатных фирм о времени актуальности 100 и менее мсек – для ОС Windows это бред.

По поводу задержки – «что бы не висло».. с таким тайменгом Вы при всем желании не заметите «висение», а вот если у Вас это в цикле крутится, то как верно заметили – открывайте новый поток, и в нем реализуйте опрос/задержки. Иначе никак.

To ALL:
Не забываем, что работает принцип карусели, с четко определенным квантом времени на контекст процессора и на переключение между контекстами, к тому же, переключение не линейное а в зависимости от приоритета, откуда ясно что уровень ядра имеет больший приоритет. Следовательно, когда дойдет очередь до вашего процесса – никто не скажет. Кванты времени на контекст и переключение между ними – тайна MS. Но даже, зная это, приоритетность задач (очередь приоритетов) не даст возможности провести точный расчет и как следствие дать однозначную гарантию. Любой вызов любой функции – есть уже задача переключения, следовательно, использование GetTickCount – простой вызов получения информации по «тикам».. т.е. «сколько их на момент получения ресурса функцией GetTickCount».. :))))

Использование ASM в системах NT весьма не так просто, особо, человеку, который задаёт такой вопрос. Да й как Вы это представляете??? Отнять у ОС её время????

Форма ответа