Неадекватные таймеры, как быть?
От: Ushastyy  
Дата: 18.09.09 13:04
Оценка:
Здравствуйте. Наверно такая проблема возникала, поделитесь советом.
Задача: Программа на VS2008C# должна выполнять действие через точный интервал времени.
Проблема: На разных компах таймер срабатывает с разной погрешностью.

Например
На компе P4 3.0 Ггц таймер 200 миллисекунд отрабатывает с точностью до 0.5 миллисекунды.
На Р4 3.2 Ггц тот же таймер срабатывает стабильно на 5-6 мс позже.
На двухядерном таймер на 200мс срабатывает раньше на 30 мс!

Сначала использовал обычный таймер System.Threading.Timer.
Потом попробовал использовать
ThreadPool.RegisterWaitForSingleObject(ev, _whaitTimerDelegate, null, interval, true);

на этом форуме вычитал вот этот таймер
[DllImport("WinMM.dll", SetLastError = true)]
        private static extern uint timeSetEvent(int msDelay, int msResolution,
                    TimerEventHandler handler, ref int userCtx, int eventType);


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

Как же всётаки добиться одинакового срабатываения таймера? Есть ли другие возможности или таймеры? За ранее спасибо за любое мнение.
Re: Неадекватные таймеры, как быть?
От: nikov США http://www.linkedin.com/in/nikov
Дата: 18.09.09 13:13
Оценка: 1 (1) +1
Здравствуйте, Ushastyy, Вы писали:

U>Как же всётаки добиться одинакового срабатываения таймера?


Нужна realtime OS.
Re: Неадекватные таймеры, как быть?
От: Аноним  
Дата: 18.09.09 13:55
Оценка:
Здравствуйте, Ushastyy, Вы писали:

U>Как же всётаки добиться одинакового срабатываения таймера?


Создайте поток с приоритетом System.Threading.ThreadPriority.Highest, внутри него вызовите System.Threading.Thread.Sleep(millisecondsTimeout). Погрешность срабатывания будет минимальной. Но не забывайте про существование системного кванта времени (в современных ОС он обычно равен 4 миллисекунды) -- точнее него не будет как ни старайтесь.
Re[2]: Неадекватные таймеры, как быть?
От: Codechanger Россия  
Дата: 18.09.09 14:21
Оценка:
Здравствуйте, nikov, Вы писали:

N>Здравствуйте, Ushastyy, Вы писали:


U>>Как же всётаки добиться одинакового срабатываения таймера?


N>Нужна realtime OS.


Или расширение реального времени типа RTX. На С# данную задачу решить принципиально нельзя.
Re: Неадекватные таймеры, как быть?
От: TK Лес кывт.рф
Дата: 18.09.09 15:01
Оценка: 19 (1)
Здравствуйте, Ushastyy, Вы писали:

U>Задача: Программа на VS2008C# должна выполнять действие через точный интервал времени.

U>Проблема: На разных компах таймер срабатывает с разной погрешностью.
U>На двухядерном таймер на 200мс срабатывает раньше на 30 мс!

Чем измеряется точность срабатывания?

U>на этом форуме вычитал вот этот таймер

U>
U>[DllImport("WinMM.dll", SetLastError = true)]
U>        private static extern uint timeSetEvent(int msDelay, int msResolution,
U>                    TimerEventHandler handler, ref int userCtx, int eventType);
U>

U>Последний таймер срабатывает немного точнее, но всё равно время срабатывания очень разнится на разных компах.

Multimedia timer один из самых лучших вариантов. msResolution как раз отвечает за погрешность срабатывания. Если вы можете померять время с точностью до нескольких msec. то, поставьте таймер на чуть меньшее время и после срабатывания, остаток времени "крутите в пустом цикле".
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re: Неадекватные таймеры, как быть?
От: _FRED_ Черногория
Дата: 19.09.09 13:22
Оценка:
Здравствуйте, Ushastyy, Вы писали:

U>Здравствуйте. Наверно такая проблема возникала, поделитесь советом.

U>Задача: Программа на VS2008C# должна выполнять действие через точный интервал времени.

Какого порядка величина "точного интервала времени"?

U>Проблема: На разных компах таймер срабатывает с разной погрешностью.


Какого порядка допускается величина погрешности срабатывания?

Таймер заводится на половину величины допустимой погрешности срабатывания. При срабатывании таймера проверяется, не пора ли выполнить операцию. Если ещё не пора — ждём следующего срабатывания, если уже пора — выполняем операцию.

U>Как же всётаки добиться одинакового срабатываения таймера?


Вряд ли указанная задача вообще в такой постановке (без указания границ "одинаковости") разрешима: какая требуется точность? наносекунда? миллисекунда? десток миллисекунд?
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Неадекватные таймеры, как быть?
От: Ushastyy  
Дата: 19.09.09 16:01
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Создайте поток с приоритетом System.Threading.ThreadPriority.Highest, внутри него вызовите System.Threading.Thread.Sleep(millisecondsTimeout).


Спасибо за совет, но к сожалению картина повторилась, на одном компе отрабатывает точно, на другом раньше.
Re[2]: Неадекватные таймеры, как быть?
От: Ushastyy  
Дата: 19.09.09 16:14
Оценка:
Здравствуйте, TK, Вы писали:

TK>Чем измеряется точность срабатывания?



Stopwatch _stopWatch = new Stopwatch();
_stopWatch.Reset();
_stopWatch.Start();
Thread.Sleep(50);
_stopWatch.Stop();
textBoxLog.Text += "\r\n" + string.Format(" Время срабатывания {0}", _stopWatch.Elapsed.TotalMilliseconds);


TK>Multimedia timer один из самых лучших вариантов. msResolution как раз отвечает за погрешность срабатывания. Если вы можете померять время с TK>точностью до нескольких msec. то, поставьте таймер на чуть меньшее время и после срабатывания, остаток времени "крутите в пустом цикле".


не понял)
Re[2]: Неадекватные таймеры, как быть?
От: Ushastyy  
Дата: 19.09.09 16:26
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Какого порядка величина "точного интервала времени"?


50 — 2000 миллисекунд

_FR>Какого порядка допускается величина погрешности срабатывания?


допускается погрешность около 2%, тоесть для 50 это 1 мс максимум

_FR>Таймер заводится на половину величины допустимой погрешности срабатывания. При срабатывании таймера проверяется, не пора ли выполнить операцию. Если ещё не пора — ждём следующего срабатывания, если уже пора — выполняем операцию.


Это понятно, но вот "пора" выполнять операцию будет ровно через заданное время, а время в разных компьютерах течёт почему-то по-разному) повторюсь, на некоторых компах отрабатывает с точностью до 0.5 мс! из-за чего мне совершенно непонятно.
Re[3]: Неадекватные таймеры, как быть?
От: _FRED_ Черногория
Дата: 19.09.09 16:36
Оценка:
Здравствуйте, Ushastyy, Вы писали:

_FR>>Какого порядка величина "точного интервала времени"?

U>50 — 2000 миллисекунд

Нормально, можно работать.

_FR>>Какого порядка допускается величина погрешности срабатывания?

U>допускается погрешность около 2%, тоесть для 50 это 1 мс максимум

Мдамс, если не секрет, что за операции?

_FR>>Таймер заводится на половину величины допустимой погрешности срабатывания. При срабатывании таймера проверяется, не пора ли выполнить операцию. Если ещё не пора — ждём следующего срабатывания, если уже пора — выполняем операцию.


U>Это понятно, но вот "пора" выполнять операцию будет ровно через заданное время, а время в разных компьютерах течёт почему-то по-разному)


При чём тут "разные компьютеры"? Почему становится важным то, что "время в разных компьютерах течёт почему-то по-разному"

Опиши конкретную решаемую задачу. "Как же всётаки добиться одинакового срабатываения таймера?" — не совсем понятно: нужно, что бы одновременно запущенные на разных компьютерах таймеры срабатывали так же одновременно или что-то другое?
Help will always be given at Hogwarts to those who ask for it.
Re[4]: Неадекватные таймеры, как быть?
От: Ushastyy  
Дата: 19.09.09 16:57
Оценка:
Здравствуйте, _FRED_, Вы писали:


_FR>Опиши конкретную решаемую задачу. "Как же всётаки добиться одинакового срабатываения таймера?" — не совсем понятно: нужно, что бы одновременно запущенные на разных компьютерах таймеры срабатывали так же одновременно или что-то другое?


Да, наверно сразу следовало бы описать более конкретно. Есть некие движущиеся по ленте объекты, и есть некий прибор который работает с движущимися объектами. Необходимо подать команду на прибор точно в момент прохождения объекта под прибором. Знаем скорость ленты, знаем расстояние датчика положения до прибора, следовательно можем вычислить время через которое нужно подать сигнал на прибор, а таймеры подводят.
Re[3]: Неадекватные таймеры, как быть?
От: TK Лес кывт.рф
Дата: 19.09.09 18:44
Оценка:
Здравствуйте, Ushastyy, Вы писали:

TK>>Multimedia timer один из самых лучших вариантов. msResolution как раз отвечает за погрешность срабатывания. Если вы можете померять время с TK>точностью до нескольких msec. то, поставьте таймер на чуть меньшее время и после срабатывания, остаток времени "крутите в пустом цикле".


U>не понял)


В предыдущем примере делаете Sleep на 40msec и потом цикл while (_stopWatch.Elapsed.TotalMilliseconds < 50) ; главное, только потоку приоритет поднять что-бы его не "вытеснили"
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Неадекватные таймеры, как быть?
От: TK Лес кывт.рф
Дата: 19.09.09 18:50
Оценка:
Здравствуйте, Ushastyy, Вы писали:

U>Это понятно, но вот "пора" выполнять операцию будет ровно через заданное время, а время в разных компьютерах течёт почему-то по-разному) повторюсь, на некоторых компах отрабатывает с точностью до 0.5 мс! из-за чего мне совершенно непонятно.


Реализация Stopwatch зависит от используемого железа. Где-то, оно может считать циклы процессора, а где-то использовать сторонний таймер...
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[5]: Неадекватные таймеры, как быть?
От: TK Лес кывт.рф
Дата: 19.09.09 19:12
Оценка: +2
Здравствуйте, Ushastyy, Вы писали:

U>Да, наверно сразу следовало бы описать более конкретно. Есть некие движущиеся по ленте объекты, и есть некий прибор который работает с движущимися объектами. Необходимо подать команду на прибор точно в момент прохождения объекта под прибором. Знаем скорость ленты, знаем расстояние датчика положения до прибора, следовательно можем вычислить время через которое нужно подать сигнал на прибор, а таймеры подводят.


Возьмите какой-нибудь аппартный котроллер который, будет управлять прибором по сигналам с компьютера.
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[3]: Неадекватные таймеры, как быть?
От: Аноним  
Дата: 20.09.09 18:32
Оценка:
Здравствуйте, Ushastyy, Вы писали:

U>...на одном компе отрабатывает точно, на другом раньше.


Назовите пожалуйста параметры компьютера на котором случается эта неприятность, интересно. Я, например, однажды наблюдал аномалию с плавающим значением System.Environemt.TickCount на многопроцессорном сервере (не многоядерном, а именно многопроцессорном).
Re: Неадекватные таймеры, как быть?
От: Аноним  
Дата: 20.09.09 19:33
Оценка: 11 (1)
U>Задача: Программа на VS2008C# должна выполнять действие через точный интервал времени.

Это как раз и есть то, что должна обеспечивать операционная система реального времени (RTOS), которой Windows не является.

Так что на Windows это, в общем случае, невозможно. Тем более, в сочетании с дотнетом.

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

Во-первых, самое простое, что можно сделать — это вызвать timeBeginPeriod(1) в начале программы и timeEndPeriod(1) в конце, чтобы установить квант времени в 1 мс (по умолчанию он 16 мс).

Еще можно задрать приоритеты потоку и процессу.

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

Очевидно, если у меня параллельно с программой будет запущен дефрагментатор диска, 3ds Max, который будет рендерить трехмерную сцену, программа сжатия Full-HD видео, и еще открыта пара сотен веб-страниц, на каждой из которых есть флеш-ролики, то вовремя выполнять свои действия твоя программа вряд ли сможет, даже если очень захочет.

Но здесь еще есть проблема в самом фреймворке. Такие вещи как JIT-компиляция, сборка мусора и вообще вся невидимая работа, которую выполняет фреймворк, делают реакцию программы во времени недетерминируемой. Возможно, это самая большая проблема.

Может быть, на C++ при определенных условиях эту задачу можно было бы почти решить (то есть программа работала бы нужным образом 99% времени, при соблюдении всех условий), но с дотнетом в этом отношении будет гораздо сложнее.

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

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

То есть, требования должны предъявляться и к самому железу.

И так далее, и тому подобное.

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

Предлагаю поискать другое решение проблемы. Кстати, в чем твоя задача, если не секрет, для чего нужно такое необычное требование?
Re[5]: Неадекватные таймеры, как быть?
От: _FRED_ Черногория
Дата: 20.09.09 20:26
Оценка:
Здравствуйте, Ushastyy, Вы писали:

_FR>>Опиши конкретную решаемую задачу.


U>Да, наверно сразу следовало бы описать более конкретно. Есть некие движущиеся по ленте объекты, и есть некий прибор который работает с движущимися объектами. Необходимо подать команду на прибор точно в момент прохождения объекта под прибором. Знаем скорость ленты, знаем расстояние датчика положения до прибора, следовательно можем вычислить время через которое нужно подать сигнал на прибор, а таймеры подводят.


Действительно ли точность скорости ленты — это плюс-минус 1 мс на расстояние от датчика до прибора?

Имхо, довольно прецизионно. Почему бы не поставить между датчиком ("положения до прибора") и прибором ("который работает с … объектами") необходимой точности реле, которое подовало бы команду прибору а, заодно (если необходимо), и на компьютер? Или же не поставить датчик в непосредственной близости (прямо напротив, например) от прибора?

Мне кажется, что эту задачку лучше решать конструкторскими приёмами, а не програмными. А если требуется именно програмными — то нужно знать больше деталей.
Help will always be given at Hogwarts to those who ask for it.
Re[2]: Неадекватные таймеры, как быть?
От: Pavel Dvorkin Россия  
Дата: 21.09.09 06:45
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Может быть, на C++ при определенных условиях эту задачу можно было бы почти решить (то есть программа работала бы нужным образом 99% времени, при соблюдении всех условий), но с дотнетом в этом отношении будет гораздо сложнее.


Нет. И на С++ ее нельзя надежно решить. Windows квантует время на уровне потоков, а не процессов, поэтому безразлично, кто причина задержки — GC в .Net-программе или же некий поток в процессе System, который именно сейчас проснулся по какой-то причине. Задача в Windows нерешаемая.
With best regards
Pavel Dvorkin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.