Я бы добавил следующее относительно MusiGenesis Ответ за Время повторной синхронизации.
Значение: какое время я должен использовать для повторной синхронизации (_maxIdle
в MusiGenesis ответов)
Вы знаете, что с этим решением вы не совсем точны, поэтому вы выполняете повторную синхронизацию.
Но то, что вы неявно хотите, - это то же самое, что решение Ian Mercer :
уникальная метка времени, расположенная в строгом порядке возрастания
Следовательно, промежуток времени между двумя повторными синхронизациями (_maxIdle
Давайте назовем это SyncTime ) должен быть функцией 4 вещей:
-
DateTime.UtcNow
разрешение
- требуемый коэффициент точности
- уровень точности, который вы хотите
- Оценка коэффициента несинхронизации вашей машины
Очевидно, что первое ограничение на эту переменную будет:
коэффициент несинхронизации <= коэффициент точности </strong>
Например: я не хочу, чтобы моя точность была хуже 0,5 с / ч или 1 мс / день и т. Д. (На плохом английском: я не хочу быть более неправильной, чем 0,5 с / ч = 12 с / день).
Таким образом, вы не можете добиться большей точности, чем то, что секундомер предлагает вам на вашем ПК. Это зависит от вашего отношения несинхронизации, которое может быть не постоянным.
Другим ограничением является минимальное время между двумя повторными синхронизациями:
Synctime> = DateTime.UtcNow
разрешение
Здесь точность и точность связаны между собой, потому что если вы используете высокую точность (например, для хранения в БД), но с меньшей точностью, вы можете нарушить оператор Иана Мерсера , который является строгим порядком возрастания.
Примечание: Похоже, DateTime.UtcNow может иметь большее значение по умолчанию Res, чем 15 мс (1 мс на моем компьютере) Перейдите по ссылке:
Высокая точность DateTime.UtcNow
Давайте рассмотрим пример:
Представьте себе коэффициент несинхронизации, прокомментированный выше.
Примерно через 10 часов он опередил на 5 секунд.
Скажи, я хочу точность в микросекундах. Мой таймер res составляет 1 мс (см. Примечание выше)
Итак, точка за точкой:
-
DateTime.UtcNow
разрешение: 1 мс
- коэффициент точности> = коэффициент несинхронизации,
давайте возьмем максимально точную, так что: коэффициент точности = коэффициент несинхронизации
- требуемый уровень точности: 1 мкс
- Оценка коэффициента несинхронизации вашей машины: 0,5 с / час (это тоже моя точность)
Если вы сбрасываете каждые 10 секунд, представьте, что вы на 9,999 с, 1 мс до сброса.
Здесь вы делаете звонок в течение этого интервала. Время, в течение которого ваша функция будет отображаться, будет впереди: 0,5 / 3600 * 9,999 с или 1,39 мс.
Вы бы отобразили время 10.000390сек. После отметки UtcNow, если вы позвоните в течение 390 микросекунд, ваш номер будет уступать предыдущему. Хуже, если это несинхронизированное отношение является случайным в зависимости от загрузки процессора или других факторов.
Теперь, допустим, я поставил SyncTime на минимальное значение> Я повторно синхронизирую каждые 1 мс
При таком же размышлении я опередил бы меня на 0,139 мкс <ниже, чем желаемая точность. Поэтому, если я вызову функцию в 9,999 мс, то есть за 1 микросекунд до сброса я нанесу график 9,999. И сразу после того, как я буду строить 10.000. У меня будет хороший заказ. </p>
Таким образом, здесь другое ограничение: коэффициент точности x SyncTime <уровень точности, скажем, чтобы быть уверенным, поскольку число может быть округлено до того, что <strong>коэффициент точности x SyncTime <уровень точности / 2 </strong> является хорошим.
Проблема решена.
Итак, быстрое резюме будет:
- Получить разрешение по таймеру.
- Вычислить оценку несинхронизированного отношения.
- коэффициент точности> = оценка несинхронного отношения, Наилучшая точность = коэффициент несинхронизации
- Выберите уровень точности, учитывая следующее:
- разрешение по таймеру <= SyncTime <= PrecisionLevel / (2 * коэффициент точности) </strong>
- Наилучшая точность, которую вы можете достичь, - разрешение по таймеру * 2 * Несинхронизированный коэффициент
Для указанного выше соотношения (0,5 / час) правильный SyncTime будет 3,6 мс, поэтому округляется до 3 мс .
При вышеуказанном соотношении и разрешении таймера 1 мс. Если вам нужен уровень точности в один такт (0,1 микросекунды), вам необходимо соотношение несинхронизации не более: 180 мс / час.
В своем последнем ответе на свой собственный ответ MusiGenesis состояние:
@ Hermann: я проводил аналогичный тест в течение последних двух часов (без коррекции сброса), и таймер на основе секундомера работает только примерно на 400 мс вперед через 2 часа, поэтому сам перекос кажется переменная (но все еще довольно серьезная). Я очень удивлен, что перекос это плохо; Я думаю, именно поэтому секундомер в System.Diagnostics. - MusiGenesis
Таким образом, точность секундомера близка к 200 мс / час, почти к нашим 180 мс / час. Есть ли какая-нибудь связь с тем, почему наш номер и этот номер так близки? Не знаю Но этой точности нам достаточно для достижения Tick-Precision
Наилучший уровень точности: для приведенного выше примера это 0,27 мкс.
Однако что произойдет, если я позвоню несколько раз между 9,999 мс и повторной синхронизацией.
2 обращения к функции могут закончиться тем, что будет возвращен один и тот же TimeStamp, время будет 9,999 для обоих (поскольку я не вижу большей точности). Чтобы обойти это, вы не можете коснуться уровня точности, потому что он связан с SyncTime вышеупомянутым отношением. Таким образом, вы должны реализовать решение Ian Mercer для этих случаев.
Пожалуйста, не стесняйтесь комментировать мой ответ.