Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Вниз

Таймер программно   Найти похожие ветки 

 
InfMag ©   (2004-11-07 19:06) [0]

Как мне создать таймер программно? Без формы и не теряя приемуществ обычного таймера.


 
KilkennyCat ©   (2004-11-07 19:08) [1]

работа с потоками. Создаешь поток, в нем счетчик, основанный на gettickcount


 
InfMag ©   (2004-11-07 19:19) [2]

Ну а пример программы? Или ссылочку на уже тут прописавшуюся тему?


 
snake1977   (2004-11-07 19:20) [3]

http://delphimaster.net/view/1-1099292775/


 
Ihor Osov'yak ©   (2004-11-07 19:28) [4]

2 [1] KilkennyCat ©   (07.11.04 19:08)

И рискуем нарваться на конкретный подгруз системы. В случае неакуратной реализации.

По сабжу. Не совсем понятен смысл вопроса. Если имеется ввиду "создание" не в дизайн-тайме компонентокиданием - то так-же, как и создание любого другого компонента в рантайме.
Если имеется ввиду без услуг vcl - то SetTimer (не забывая  про KillTimer), либо самозапирание потока на каком-то обьекте синхронизации с таймаутом с помощью WaitForSingleObject.. Иногда можно обычный sleep (тогда "самозапирание" c таймаутом делает система)..
Следует иметь ввиду, что варианты  с "запиранием" плохо выглядять в случае вызова из главного потока - тогда "замораживается" интерфейс.. В таком случае можно сделать что-то типа  нижеследующего

procedure _Pause01;
var
 t: tdatetime;
const
 delta = 1.0 / 24.0 / 60 / 60 / 10;
begin
 t := now;
 repeat
   if GetQueueStatus(QS_ALLEVENTS) <> 0 then
     Application.ProcessMessages
   else
     sleep(10);

   if abs(t - now) > delta then
     break;
 until false;

end;


да,  пожалуй, здесь лучше вместо now ориентироваться все же на GetTickCount..

еще для избежания "заморозки" вместо WaitFor.. можно использовать
MsgWaitForMultipleObjects ..


 
KilkennyCat ©   (2004-11-07 19:30) [5]


> Ihor Osov"yak ©   (07.11.04 19:28) [4]


согласен, но если требуется точный таймер, без нити не обойтись.


 
Ihor Osov'yak ©   (2004-11-07 19:34) [6]

> согласен, но если требуется точный таймер, без нити не обойтись.

ну, еще бы на уровень 0 прыгнуть, там отсчет доступен с дискретностью 100 наносекунд :-).
Только вот потом проблема, что все достигнутая точность уйдет коту под хвост вследствии некоторой непрогнозированности задержки на переключение потоков..


 
KilkennyCat ©   (2004-11-07 19:38) [7]


> Ihor Osov"yak ©   (07.11.04 19:34) [6]


да... 100 наносекунд - тут уже почти и к железным проблемам подбираемся... но наверное, можно приблизительно подсчитать золотую середину, когда необходимо работать с потоком, а когда уже бесполезно, или излишне.


 
Defunct ©   (2004-11-07 20:34) [8]

> непрогнозированности задержки на переключение потоков..

разве tpTimeCritical не решает этот вопрос?


 
Ihor Osov'yak ©   (2004-11-07 21:23) [9]

нет, не решает. Во превых, это поднимает только приоритет потока, но не уменшает задержек на переключение. Во вторых - и это более важно - всякие там tpTimeCritical - вещь не абсолютная, а относительна касательно к базовому приоритету процесса. В третих же - и это еще более существенно - все потоки пользовательского режима (даже если сделать SetPriorityClass + SetThreadPriority по максимуму) - по любому будут иметь ниже приоритет, чем потоки режима ядра, даже на самом захудалом уровне приоритетов... Не гороря уже за приоритеты кода, выполняющего обработку прерываний..


 
KilkennyCat ©   (2004-11-07 21:28) [10]

из чего и сделаем вывод: реалтайм - вещь специфичная и решается специальными методами.


 
Defunct ©   (2004-11-07 21:55) [11]

Ihor Osov"yak ©   (07.11.04 21:23) [9]

Вы так все описали, что можно подумать записать компакт диск на старых приводах с маленьким буфером записи и без burn proof является невыполнимой задачей.

> по любому будут иметь ниже приоритет, чем потоки режима ядра
чем поток планироващика - да.

ох и да, прошу прощения не заметил явное несоовтветствие сразу -100 наносекунд прочитал как 100 ms. Уверяю вас, точности в 100 нс в виндовсе нет даже на уровне ядра (10 ms по рихтеру) а если открыть старенького Джордейна то увидим что макс. частота системного таймера (~1.3Mhz что соответствуею ~1 mks но никак не 100 нс).


 
GuAV ©   (2004-11-07 22:09) [12]

InfMag ©   (07.11.04 19:06)
Как мне создать таймер программно? Без формы и не теряя приемуществ обычного таймера.


SetTimer(0, 0, N, @MyTimerProc);


 
Ihor Osov'yak ©   (2004-11-07 22:16) [13]

2 [11] Defunct ©   (07.11.04 21:55)

> что можно подумать записать компакт диск на старых приводах с маленьким буфером записи и без burn proof является невыполнимой задачей.

Свой первый диск я записывал еще в 97 году. На момент записи снимались все лишние процессы и отключалась сеть. Если этого не сделать -  выход был менее 50 процентов..

> точности в 100 нс в виндовсе нет даже на уровне ядра

Точность - понятие очень относительное, а вот если говорить об дискретности программирования временных интервалов, то иногда лучше жевать, чем говорить (см. ниже).

> а если открыть старенького Джордейна
я не говорил, что речь идет о системе на базе 8086/8088. Что это не так, можно было бы догадаться хотя бы по упоминанию режима ядра. То есть, что речь идет как минимум о 386.

да, еще. Посмотрите на описание KeWaitForSingleObject, KeSetTimer и иже с ними - обратите внимание на дискретность задания временных интервалов. Подсказка - смотреть нужно не в msdn, а в ddk от систем nt-шного ряда.


 
Ihor Osov'yak ©   (2004-11-07 22:24) [14]

ладно, привожу выдержку из ддк-овской докуентации:

KeSetTimer
KeSetTimer sets the absolute or relative interval at ....

BOOLEAN
 KeSetTimer(
   IN PKTIMER  Timer,
   IN LARGE_INTEGER  DueTime,
   IN PKDPC  Dpc  OPTIONAL
   );
...

DueTime
Specifies the absolute or relative time at which the timer is to expire. If the value of the DueTime parameter is negative, the expiration time is relative to the current system time. Otherwise, the expiration time is absolute. The expiration time is expressed in system time units (100-nanosecond intervals). Absolute expiration times track any changes in the system time; relative expiration times are not affected by system time changes.

Понятно, что чудес не бывает, и

The expiration of the timer ultimately depends on the granularity of the system clock. The value specified for DueTime guarantees that the timer object is set to a signaled state on or after the given DueTime. However, KeSetTimer cannot override the granularity of the system clock, whatever the value specified for DueTime.

Но тот факт, что в современных системах тактовая частота значительно выше, чем частота в стареньком оригинальном PC, надеюсь, есть известным.. И что в качестве системного таймера используется уже не i8053 с его ~1.3Mhz тактовой частотой.


 
Piter ©   (2004-11-07 22:25) [15]

ИЗ БУДУЩЕГО FAQ:

Вопрос: как создать таймер средствами Win32Api

Ответ: нужно воспользоваться функцией SetTimer, описанной в Windows.pas следующим образом:

function SetTimer(hWnd: HWND; nIDEvent, uElapse: UINT;
 lpTimerFunc: TFNTimerProc): UINT; stdcall;

hWnd - указатель на окно, куда будут посылаться сообщения WM_TIMER при очередной итерации таймера
nIDEvent - задает идентификатор таймера, не должен быть ноль. Игнорируется системой, если hWnd равно нулю
uElapse - время в миллисекундах между итерациями таймера
lpTimerFunc - указатель на процедеру TimepProc, которая должна являться callback функией и которая будет вызываться системой при каждой итерации таймера

Видно, что существую два пути задания таймера - или задать окно hWnd, куда будут посылаться сообщения WM_TIMER каждые uElapse миллисекунд, или задать указатель на процедуру lpTimerFunc, которая будет вызываться системой каждые uElapse миллисекунд.
Какой из способов будет использоваться, система выбирает по значению lpTimerFunc. Если оно задано, то будет вызывать TimerProc функцию, если передается nil - то будет посылаться сообщение заданному окну.

1) Рассмотрим первый вариант:

procedure TForm1.Button1Click(Sender: TObject);
begin
 SetTimer(Handle, 1, 1000, nil);
end;

После нажатия на Button1 экземпляру TForm1 каждые 1000 миллисекунд (1 секунду) будет посылться сообщения WM_TIMER. Естественно, нужно это сообщение обрабатывать. У TForm1 объявить метод:

TForm1 = class(TForm)
...
 procedure WMTImer(var Msg: TMessage); message WM_TIMER;
...

И реализовать:

procedure TForm1.WMTImer(var Msg: TMessage);
begin
 beep;
end;

Каждую секунду будем издавать звуковой сигнал.

2) теперь рассмотрим второй варинт, на основе процедуры TimerProc. Вызов будет такой:

idTimer := SetTimer(0, 0, 1000, @TimerProc);

В качестве указателя на окно пишем ноль, во второй параметр пишем что хотим (все равно игнорируется), третий - время итераций, четвертый - указатель на процедуру TimerProc, которая будет вызываться системой каждые 1000 миллисекунд. Где-то должна быть объявлена:

procedure TimerProc(wnd: HWND; Msg: UINT; idEvent: UINT; Time: DWORD); stdcall;
begin
 beep;
end;

Где wnd - указатель на окно, которое передали функции SetTimer (в нашем случае ноль); Msg - номер сообщения (оно будет равно WM_TIMER); idEvent - идентификатор таймера; Time - время в миллисекундах, которое прошло с момента загрузки windows на момент генерации этого события таймера (данное значение эквивалентно тому, что возвращает функция GetTickCount).

Делает этот код тоже самое, что и первый пример - издает сигнал каждую секунду. При этом никакие передаваемые аргументы я не анализирую. Хотя, например, можно создать два таймера и назначить им одинаковую TimerProc. А различать вызовы от одного и другого таймеров по значению idEvent.

Значение, возвращаемое функцией SetTimer сохраняется в какую-нибудь переменную idTimer. Это нужно, чтобы потом можно было удалить таймер, так как во втором примере id таймера назначется системой.

Также имеет смысл проверять значение, возвращаемой функцией SetTimer, в любом случае. Если она вернет ноль - то таймер создать не удалось, иначе она вернет идентификатор таймера. В первом примере SetTimer вернет тот идентификатор, которйы мы ему сами и назначили. Во втором примере назначение идентификатора система игнорирует (так как hWnd равно нулю), поэтому сама выбирает значение идентификатора - поэтому его и надо запомнить.

Чтобы удалить таймер надо просто вызвать функию KillTimer, передав ей Handle окна (который указывали при создании таймера) и идентификатор таймера.

1) для первого случая:

KillTimer(Handle, 1);

2) ддя второго случая:

KillTimer(0, idTimer);

Файл проекта с данным примером можно загрузить ЗДЕСЬ

Отвечал: Piter


 
Defunct ©   (2004-11-07 22:35) [16]

> Свой первый диск я записывал еще в 97 году. На момент записи снимались все лишние процессы и отключалась сеть. Если этого не сделать -  выход был менее 50 процентов..

С этим я согласен, однако это опровергает ваши слова:
> по любому будут иметь ниже приоритет, чем потоки режима ядра
Потоки режима ядра вы ведь не снимали.

> Точность - понятие очень относительное, а вот если говорить об дискретности программирования временных интервалов, то иногда лучше жевать, чем говорить (см. ниже).

Уважаемый Игорь, не надо меня отправлять за орбитом, я его конечно не против пожевать, но здесь вы хотите так все повернуть, что мол я должен жевать а у вас типа все гладко. Не выйдет, ваши слова:

> ну, еще бы на уровень 0 прыгнуть, там отсчет доступен с дискретностью 100 наносекунд :-).
Только вот потом проблема, что все достигнутая точность уйдет коту под хвост вследствии некоторой непрогнозированности задержки на переключение потоков..


> я не говорил, что речь идет о системе на базе 8086/8088. Что это не так, можно было бы догадаться хотя бы по упоминанию режима ядра. То есть, что речь идет как минимум о 386.

Не имеет разницы, таймер остался прежним. (1.3 Mhz, и его вполне хватает для любых нужд ОС).

> да, еще. Посмотрите на описание KeWaitForSingleObject, KeSetTimer и иже с ними - обратите внимание на дискретность задания временных интервалов.

Нет проблем, видел описание раньше.

> Подсказка - смотреть нужно не в msdn, а в ddk от систем nt-шного ряда.

А зачем смотреть ddk для nt ядра, если аппаратные средства все равно не способны дать такую точность?


 
GuAV ©   (2004-11-07 22:38) [17]

Кстати по этому давно волнующий меня вопрос -
procedure TimerProc(wnd: HWND; Msg: UINT; idEvent: UINT; Time: DWORD); stdcall;


Она вызывается не при обаботке сообщений а в любой момент. Должен ли быть код в нутри неё потокобезопасным ? создаёт ли такоё таймер "неявный" дополнительный поток ?


 
Defunct ©   (2004-11-07 22:41) [18]

[16].

написал до того как запостили [14, 15]
поэтому
2 Ihor: ладно забей, это от скуки начал к словам придераться.


 
Ihor Osov'yak ©   (2004-11-07 22:54) [19]

2 [15] Piter ©   (07.11.04 22:25)

Хоть я и обещал тебя в глубокий игнор, но раз ты составляешь FAQ - несколько дополнений.
Не рассмотрен еще один вариант использования таймера, а именно - и хендл, и процедура - нулевые, то есть SetTimer(0, 0, NNNN, 0);

В таком случае таймер будет просто посылать WM_Timer в очередь потока, в котором был создан таймер. Сообщение обрабатываем в цыкле выборки сообщений. Здесь есть одна очень красивая возможность получить грабли. Дело в том, что очень часто либо сам разработчик, либо в коде стороних модулей, которые выполняются в потоке создавшем таймер делают альтернативные цыклы обработки сообщений, что-то типа

while getmessage() do
begin
 case Msg.Message of ..
 end;
 DispatchMessage(Msg);
end;

хотя бы для организации некоторых временных задержек. Так вот, во время, когда будет работать такой цикл, наш обработчик сообщения для потока это сообщение не получит - ведь обработчик то в главном цыкле, а альтернативный цыкл WM_Timer просто проигнорирует, либо обработает совсем не так, как нам нужно - ведь там будет не наш код.  Аналогичной проблемы при использовании хендла окна не будет, при условии естественно, что в альтернативном цыкле будет стоять DispatchMessage (мы все же надеемся, что программисты народ здравомыслящий в своем большинстве). Такой же проблемы вероятнее всего не существуеь и при втором способе - так как отложенный вызов процедуры таймера вероятнее всего делается где-то в глубине getmessage или ему подобных - но это догадка, я этого вопроса не исследовал..

Третий cпособ я упомянул лишь для полноты картины. Но. Его наверное все же можно использовать, если есть гарантия, что альтернативных циклов не будет..

Еще один неочевидный ньюанс с таймерами (независимо от способа). Если в очереди потока стоит хотя бы одно необработанное сообщение от таймера (или явное для третьего варианта, либо неявные для вариантов 1 и 2) - то новое сообщение от таймера в очередь помещаться не будет. МS наверное это сделал специально, чтобы исключить забиение очереди необработанными сообщениями какого-то не в меру шустрого таймера по отношению к обработчикам остальных сообщений (или одного из них)... Этим ньюансом и объясняется то обстоятельство, что "таймер иногда тормозит"...


 
Ihor Osov'yak ©   (2004-11-07 22:59) [20]

2 [18] Defunct ©

Не нужно говорить, что мне делать - и я тогда не буду говорить, куда Вам следует идти.. (с).

В дополнение - научитесь читать внимательно и не искажать смысл однозначно написанных вещей.


 
Defunct ©   (2004-11-07 23:14) [21]

Ihor Osov"yak ©   (07.11.04 22:59) [20]

> В дополнение - научитесь читать внимательно и не искажать смысл однозначно написанных вещей.

Если вы заметили, то меня там неустроило высказывание:
> Только вот потом проблема, что все достигнутая точность уйдет коту под хвост вследствии некоторой непрогнозированности задержки на переключение потоков..
Про что я специально переспросил в [8]. После чего вы приплели приоритеты потоков ядра в [9]. Соответственно я вам указал на неспособность аппаратных средств обеспечить точность 100нс даже для потоков ядра.

Поэтому мне последнее ваше высказывание [20] крайне не понравилось.
Уважаемый Игорь, сейчас уже моя очередь послать вас за орбитом. Потому что, если после всего вы все еще считаете, что в посте в [6] все гладно, тогда нам просто не о чем разговаривать.

Так кто из нас невнимательно читает?


 
Ihor Osov'yak ©   (2004-11-07 23:51) [22]

> Соответственно я вам указал на неспособность аппаратных средств обеспечить точность 100нс даже для потоков ядра.
см. ниже.

Итак смотрим.

> После чего вы приплели приоритеты потоков ядра в [9].
Повторяю медленно - повышение приоритетов потоков в пользовательском режиме проблемы не снимает, так как всегда существуют потоки режима ядра, которые имеют все без исключения более высокий приоритет чем любой поток пользовательского режима с максимальным приоритетом. Мало того, часть этих потоков с уровнем выше PASSIVE_LEVEL никогда не прерываются для обслуживания пользовательских потоков (за PASSIVE_LEVEL не уверен, а сейчас поднимать документацию нет желания). Также, если в системе появляется поток с приоритететом выше PASSIVE_LEVEL (а это довольно часто при работе кода драйверов) - выполнение пользовательского потока прерывается незамедлительно. Отсюда вывод - время ожидания получения кванта времени пользовательским потоков очень сильно зависит от того, что происходит в коде режима ядра. То есть в коде, никак не подочетном коду нашего рабочего потока, который что-то там пытается делать с таймерами...
Все выше написанное илюстрирует тот тезис, что особо точно отслеживать временной интервал в специальном потоке не имеет смысла, так как непредсказуемость задержки на переключение пользовательских потоков значительно превышает ту якобы точность, что можно достичь всякими хитрыми решениями, о чем было сказано с упоминанием какого то кота и его хвоста..

> Соответственно я вам указал на неспособность аппаратных средств обеспечить точность 100нс даже для потоков ядра.

Повторяю еще раз. Я вел речь о дискретности интервала программирования временных задержек. Но никак не о точности. Если Вы не видите различия между дискретностью и точностью - то я в лучшем случае могу посоветовать почитать книжки.

Теперь смотрим еще раз [11]. Здесь Вы почему то вытащили платформу, совершенно не имеющую отношения к тому, что я говорил в контексте дискретности величиной в 100 наносекунд.

О чем я пытался обьяснить в дальнейших постингах.

> Соответственно я вам указал на неспособность аппаратных средств обеспечить точность 100нс даже для потоков ядра.

Где? Там, где было упомянута платворма на 8088? Я повторяю раз наверное уже четвертый - к контексту разговора о 100 наносекундном интервале эта платформа не имеет ни малейшего отношения.

>все еще считаете, что в посте в [6] все гладно

я это не считаю. Я знаю, что дело обстоит именно так. Знаю на основании изучения соотв. документации на архитектуру системы, на программное и аппаратное обеспечение, а также некоторых практических экспериментов.

> Так кто из нас невнимательно читает?

Попробуйте угадать..

Да, еще. Лично мне глубоко безразлично Ваше мнение по этому вопросу. На сем дискуссию с Вами оканчиваю.


 
GuAV ©   (2004-11-07 23:56) [23]

[17] - никто не знает ?


 
Defunct ©   (2004-11-08 00:35) [24]

Удалено модератором
Примечание: Бех грубостей


 
Ihor Osov'yak ©   (2004-11-08 00:43) [25]

2 [17] GuAV ©   (07.11.04 22:38)

> Она вызывается не при обаботке сообщений а в любой момент.

 Думаю, что это не так. Подозреваю, что вызов процедуры таймера происходит с помощью механизма APC, то есть в контексте потока, создавшего соотв. таймер и во время вызова либо какой-то функции выборки сообщения, либо во время тревожного ожидания на WaitForXXX и, возможно,  sleepEx в состоянии  Alertable..  Но это догадки. В литературе внятного изложения этого вопроса не встречал, впрочем особо и не искал - так как пока не было  практической необходисости штудировать этот вопрос...
Можете сделать тестовое приложение и проанализируете контекст потока, в котором будет вызвана процедура и сравните с потоком, который создавал таймер... Также можно сделать логирование самой процедуры и мест, непосредственно перед и после функций работы с очередью и функций тревожного ожидания (и sleepEx?)...


 
Ihor Osov'yak ©   (2004-11-08 00:55) [26]

2 Defunct

Большая просьба - не занимайтесь интерпритацией моих высказываний. Я вас на это не уполномачивал. Это во первых. А во вторых еще и потому, что вы несете ахинею.


 
GuAV ©   (2004-11-08 01:06) [27]

Ihor Osov"yak ©   (08.11.04 0:43) [25]
Думаю, что это не так. Подозреваю, что вызов процедуры таймера происходит с помощью механизма APC, то есть в контексте потока, создавшего соотв. таймер и во время вызова либо какой-то функции выборки сообщения


Очень похоже. Без очереди сообщений (в безоконном приложении) такой таймер оказывается не работает. ThreadId тот же. с GetThreadContext что делать - не знаю...


 
Defunct ©   (2004-11-08 01:08) [28]

Ihor Osov"yak ©   (08.11.04 00:55) [26]

Просьба будет исполнена.

Я просто выскажусь как надо, без всяких интерпретаций.

Точность прораммного таймера 100нс в Windows не может быть достигнута не только из-за неизвестного интервала задержки между переключениями потоков, но и из-за ограничений аппаратных средств системы: аппаратный системный таймер всего один, работает всегда с одинаковой частотой, которая не превышает 1.13Mhz (мининимально возможный гарантированный временной интервал 1mks)..


 
KilkennyCat ©   (2004-11-08 01:09) [29]


> Ihor Osov"yak ©   (07.11.04 23:51) [22]


значит, все-таки можно написать очень точный таймер с очень малым интервалом? например, как драйвер. Естественно, что события невозможно, получается, реально отобразить, но зарегистрировать и обработать в последствии вполне реально. То есть, можно написать свой собственный драйвер параллельного порта, который регистрирует свое состояние. После всего окончания процесса регистрации, идет дальнейшая обработка.
Я сделал правильный вывод? если да, то в принципе, можно сделать много интересных нереалтаймных вещей...


 
KilkennyCat ©   (2004-11-08 01:13) [30]


> Defunct ©   (08.11.04 01:08) [28]

а вот с этим уже я не соглашусь... не обязательно использовать данный аппаратный таймер. Думаю, есть другие способы отсчитать промежуток времени.


 
Defunct ©   (2004-11-08 01:21) [31]

KilkennyCat ©   (08.11.04 01:09) [29]

Очень точный таймер написать можно, который будет выдавать абсолютно ровные осцилограммы. У нас в одном из проектов системный таймер использовался для синхронизации в программной реализации многоканального последовательного интерфейса (параллельный порт работал как 8 последовательных портов).


 
Defunct ©   (2004-11-08 01:24) [32]

KilkennyCat ©   (08.11.04 01:13) [30]

нет никаких других методов.

Есть система прерываний

IRQ0 - канал таймера, вот он и дергается периодически, прерывая выполнение текущего потока и передавая управление ядру системы - планировщику, который решает кому отдать управление.


 
KilkennyCat ©   (2004-11-08 01:36) [33]


> Defunct ©   (08.11.04 01:24) [32]


совсем никаких? предположим, тупой цикл, который постоянно генерирует событие таймера. В идеале, если ничего другое не работает, скорость работы данного таймера превысит 1 МГц аппаратного. и нехило превысит. Или я ошибаюсь?


 
Defunct ©   (2004-11-08 01:47) [34]

KilkennyCat ©   (08.11.04 01:36) [33]
> совсем никаких? предположим, тупой цикл, который постоянно генерирует событие таймера. В идеале, если ничего другое не работает, скорость работы данного таймера превысит 1 МГц аппаратного. и нехило превысит. Или я ошибаюсь?

Так можно, но не забывайте, аппаратный таймер будет все равно крутиться, и будет прерывать ваш цикл, что внесет очень серьезную погрешность, порядка 1-99%!!! взависимости от используемого железа и от количества потоков в системе, приоритет которых равен или выше приоритета вашего потока в котором вы собираетесь крутить цикл.

В идеале, нужно с правами ядра перехватывать IRQ0 (вот тогда у вас будет действительно точный таймер), или повесить какое-то внешнее устройство синхронизации, по прерыванию от которого будет увеличиваться или уменьшаться значение какого-то вашего счетчика.


 
KilkennyCat ©   (2004-11-08 01:51) [35]

Как вы заметили, с помощью функции QueryPerformanceFrequency мы определяем частоту на входе счетчика таймера, а затем вычисляем величину, обратную частоте, то есть период импульсов в мкс (переменная sngUnit), после чего показания счетчика и его приращения переводим в доли секунды (мкс). Жмем на кнопку CmdPerformanceCounter, и наши труды вознаграждены ( Рис. 3) — мы получили приращения, равные приблизительно 5 мкс, причем частота счетчика таймера составляет 1193180 Гц при работе в Windows 9x/Me. Перейдя в Windows 2000/XP, получим приращения порядка 2.0—2.5 мкс при частоте 3579545. Да, и впрямь high resolution timer!

это отсюда - http://www.mycomputer.ua/text/6406;jsessionid=1C4E5BF46E1D64ACC37F7E80EE51030C


 
KilkennyCat ©   (2004-11-08 01:52) [36]


> Defunct ©   (08.11.04 01:47) [34]


однако, теоретически, я могу учесть все погрешности. Но, если это так, то проще отказаться от программирования в пользу электроники


 
Defunct ©   (2004-11-08 01:57) [37]

KilkennyCat ©   (08.11.04 01:36) [33]
Нарисую временную диаграмму работы системы для всего 6-ти
потоков и ядра, чтобы все вам стало понятно.

Обозначу:
Ваш поток - буквой X
Ядро систмы - Я
Потоки с равным приоритетом - E
потоки с более высоким приоритетом - H

Итак:


^
|XЯHHHHEEXЯHHHEEXЯHHHEEXЯ
|______________________________________________________


По оси X процессорное время.
По оси Y - выполняемый поток
Там где выполняется Я - соответствует прерыванию от аппаратного таймера (IRQ0)

Итого, как видите ваш поток будет получать какие-то остатки общего процессорного времени, о какой тут точности можно говорить?


 
Defunct ©   (2004-11-08 02:01) [38]

> однако, теоретически, я могу учесть все погрешности.

не можете.
Такой тривиальный случай - Вася Певченко начал скачивать с вашего компьютера музыку по сети и все ваш таймер получает погрешность 20-50%


 
KilkennyCat ©   (2004-11-08 02:04) [39]

теперь я еще больше запутался... получается, что скорость работы процессора совершенно не важна при выполнение только одной задачи? , то есть, простая программка, предположим, выполняющая просто одну тупую операцию, будет работать одинаково на пне 166 и на пне-4 3 ГГц?


 
KilkennyCat ©   (2004-11-08 02:05) [40]


> Defunct ©   (08.11.04 02:01) [38]

если теоретически, то учитывание погрешностей подразумевает и максимальное предотвращение их появления.



Страницы: 1 2 3 4 вся ветка

Форум: "Потрепаться";
Текущий архив: 2004.11.28;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.61 MB
Время: 0.042 c
3-1098972737
Vital
2004-10-28 18:12
2004.11.28
DBExpress и больщое кол-во транзакций


1-1100334175
AlexBragutsa
2004-11-13 11:22
2004.11.28
Для начинающего Делфиста


1-1100183086
denis24
2004-11-11 17:24
2004.11.28
qrlabel.wordwrap


3-1099388991
Tolya
2004-11-02 12:49
2004.11.28
Тип поля date и Memo


8-1093720769
clampo
2004-08-28 23:19
2004.11.28
Смена картинок по таймеру





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский