Поднять событие в интервале высокого разрешения / таймера

Я хочу использовать максимально возможный таймер разрешения с помощью c #. Например, я хочу поднять событие каждые 11 тиков (я слышал, что тик – это самый высокий счетчик в ПК). Я попробовал таймер и обнаружил, что минимальное истекшее время составляет миллисекунды. Я посмотрел на секундомер, но секундомер не поднимает события.

Благодарю.

Использование мультимедийного таймера должно дать вам около 1000 событий в секунду. Этот код должен помочь вам в этом.

public delegate void TimerEventHandler(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2); ///  /// A multi media timer with millisecond precision ///  /// One event every msDelay milliseconds /// Timer precision indication (lower value is more precise but resource unfriendly) /// delegate to start /// callBack data  /// one event or multiple events /// Dont forget to call timeKillEvent! /// 0 on failure or any other value as a timer id to use for timeKillEvent [DllImport("winmm.dll", SetLastError = true,EntryPoint="timeSetEvent")] static extern UInt32 timeSetEvent(UInt32 msDelay, UInt32 msResolution, TimerEventHandler handler, ref UInt32 userCtx, UInt32 eventType); ///  /// The multi media timer stop function ///  /// timer id from timeSetEvent /// This function stops the timer [DllImport("winmm.dll", SetLastError = true)] static extern void timeKillEvent( UInt32 uTimerID ); 

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

* Запуск более 5 таймеров серьезно замедлит работу большинства систем! Выполните как можно меньше кода в обработчиках событий и убедитесь, что исполняемый код быстрее, чем 1 миллисекунда, или сталкиваются с серьезными проблемами. Я начал делегировать каждые 10-50 тиков, чтобы увеличить отображение ярлыков.

Обычный переключатель streamа, который встречается на Thread.Sleep , оставит один ниток без вашего кода и займет около 40 миллисекунд. Вы также можете увеличить частоту переключения streamов с помощью некоторых вызовов ядра NT, но, пожалуйста, не делайте этого.

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

Для справки, часы Windows имеют точность около 10 миллисекунд (меньше в более ранних версиях). Обертка вашего кода с помощью вызовов DateTime.UtcNow не будет лучше.

В вашем вопросе вы говорите о желании «поднять событие». Проблема заключается в том, что единственным типом объекта, сохраняющего время, который вызывает событие через определенные промежутки времени, является объект Timer . Он доступен в трех разных воплощениях в .NET Framework ( System.Timers.Timer , System.Threading.Timer и System.Windows.Forms.Timer ), все из которых имеют свои собственные уникальные сценарии использования и относительные причуды, но ни один из них они гарантируют точность в любом месте, близком к тому, что вы просите . Они даже не предназначены для этого, и нет никаких эквивалентных функций, открытых API Windows, которые будут предоставлять этот тип точности.

Причина, по которой я спросил, почему вы хотите это сделать, и если вы пытаетесь провести бенчмарк, – это то, что это изменяет всю игру. .NET Framework (начиная с версии 2.0) предоставляет объект « Stopwatch который специально предназначен для точного измерения прошедшего времени для ситуации, такой как бенчмаркинг или профилирование производительности. Stopwatch просто обертывает функции Windows API QueryPerformanceFrequency и QueryPerformanceCounter (что должно подтвердить мое предложение относительно его предполагаемого использования). Раньше мы использовали P / Invoke для этих функций для доступа к этим функциям в более ранних версиях Framework, но теперь они удобно встроены. Если вам нужен таймер с относительно высоким разрешением для бенчмаркинга, Stopwatch – ваш лучший выбор. Теоретически, он может предоставить вам субмикросекундную синхронизацию.

Но это не без проблем. Он не вызывает никаких событий, поэтому, если ваш текущий дизайн зависит от обработки событий, вам придется переосмыслить его. И это тоже не гарантируется. Несомненно, он может иметь максимально возможное разрешение при использовании аппаратных ограничений, но это не означает, что он обязательно будет соответствовать вашим заявленным требованиям. Например, он может быть ненадежным в многопроцессорной системе, где Start и Stop должны выполняться на одном процессоре. Это не имеет значения, но это так . Это также подвержено ненадежности процессоров, которые могут дросселировать их тактовую частоту вверх и вниз. И осмелюсь даже упомянуть, что вызов QueryPerformanceCounter займет некоторое время – около 5 микросекунд даже на современном процессоре с частотой 2+ ГГц, что мешает вам реально достичь этого субмикросекундного времени, которое звучит хорошо в теории. Опять же, любой разумный профилировщик кода будет считать это время незначительным, потому что, ну, это так .
(См. Также: http://www.devsource.com/c/a/Techniques/High-Performance-Timing-under-Windows/2/ )

Различные classы таймеров используют большую степень детализации. Оба Threading.Timer и Timers.Timer используют 1/64 секунды, что составляет 15.625 миллисекунд.

Если «тик», о котором вы говорите, это отметка в 100 наносекунд, используемая classом DateTime, classом TimeSpan и выведенная секундомером, тогда длина 11 тиков, о которой вы спрашиваете, составляет 1100 наносекунд или 1,1 микросекунды. Насколько мне известно, встроенный таймер не даст вам такого разрешения. Если вы действительно хотите, чтобы событие происходило каждые 1,1 микросекунды, вам нужно будет удалить идею «таймера» и вместо этого подумать о короткой задержке. Сделайте stream с высоким приоритетом и запустите свое событие в цикле. Не вызывайте Thread.Sleep (), так как я считаю, что 1,1 микросекунды меньше тайм-листа системного планировщика. Вам нужно будет сделать цикл задержки.

Кроме того, понимайте, что временной интервал, о котором вы просите, очень и очень мал. 1,1 микросекунды – всего 2200 процессорных циклов на 2 ГГц процессоре. Незначительная сумма, но не много времени, чтобы проделать большую работу. Если вы говорите 1 тик, о котором вы сказали в своем комментарии, это всего лишь 200 циклов процессора: это достаточно времени, чтобы выполнить несколько десятков математических операций и, возможно, вызвать одну функцию.

  • Обновление JLabel каждые X секунд из ArrayList - Java
  • Interesting Posts

    Как отключить элемент списка ListBox на основе значения свойства?

    Написание разных значений для разных таблиц BigQuery в Apache Beam

    R для установки рабочего каталога в исходное местоположение файла в Rstudio

    Firebase Storage и Access-Control-Allow-Origin

    Определить корень проекта из запущенного приложения node.js

    Как я могу заставить LINQ вернуть объект с максимальным значением для данного свойства?

    Могу ли я вернуть JSON из веб-службы .asmx, если ContentType не является JSON?

    Как создать приятный DMG для Mac OS X с помощью инструментов командной строки?

    Создайте приложение Android Studio через командную строку

    Как перебирать диапазон дат в Java?

    Я начал получать странное сообщение «Шифрование файловой системы – Резервное копирование ключа шифрования файла»

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

    WPF DataGrid CustomSort для каждого столбца

    Как сериализовать объект в XML без получения xmlns = “…”?

    Как ограничить процесс одним ядром ЦП?

    Давайте будем гением компьютера.