Как запустить функцию с точным временем? - PullRequest
2 голосов
/ 02 ноября 2011

Мне нужна функция для запуска в точное время в пределах +/- 1 мс.Я пробовал следующее, но в итоге получилось не менее 15 мсек между исполнением.

void Main()
{
    System.Timers.Timer timer = new System.Timers.Timer(1);   // executes every 15ms
    timer.Elapsed += new System.Timers.ElapsedEventHandler(myFunction);

    System.Timers.Timer timer2 = new System.Timers.Timer(5);   // executes every 15ms
    timer2.Elapsed += new System.Timers.ElapsedEventHandler(myFunction);

    System.Timers.Timer timer2 = new System.Timers.Timer(20);   // executes every 31ms
    timer3.Elapsed += new System.Timers.ElapsedEventHandler(myFunction);

    timer.Start();
    timer2.Start();
    timer3.Start();

}

void myFunction()
{
    doWord();
}

с использованием Thread.Sleep () дает те же результаты.

Краткое содержание приложения.

Я буду читать файл, содержащий 1553 сообщения (каждое с отметкой времени).Мне нужно будет воспроизвести эти сообщения с максимально близким временем, которое содержит файл.Временные метки для сообщений записываются в микросекундах, но мне понадобится только точность мсек.

Это делается с использованием карты DDC 1553 (PCI Card).У меня есть анализатор, который позволяет мне просматривать сообщения, включая дельта-время между сообщениями, чтобы измерить мою точность.

Машина, которую я использую, имеет QuadCore с гиперпоточностью.Используя for (int i = 0; .....), я могу получить точность с .5msec.Однако это очень неэффективно и, по возможности, предпочтительнее использовать более реалистичный и даже более портативный метод.

Ответы [ 4 ]

5 голосов
/ 02 ноября 2011

.NET, C # и даже Windows в целом не являются операционными системами реального времени, подходящими для очень точной синхронизации.

Худшие варианты включают использование классов Timer и Thread.Sleep().

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

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

Обновление;Нил: если вы взаимодействуете с оборудованием с учетом времени, вы должны использовать другое решение.Вы можете сделать замкнутый цикл с Stopwatch, но он будет использовать много ресурсов процессора столько же, сколько и вы.И это не будет достаточно точным, вероятно.Например: микросхема PIC, FPGA, плата ввода-вывода или интерфейс, все остальное в основном.

1 голос
/ 02 ноября 2011

Вы можете использовать System.Threading.Timer , который имеет разумную точность. Просто помните, что он не публикуется в потоке пользовательского интерфейса, поэтому вам нужно правильно делегировать любое взаимодействие с пользовательским интерфейсом.

Для этого также можно использовать мультимедийный таймер, который имеет очень высокое разрешение по времени. Смотри http://www.codeproject.com/KB/miscctrl/lescsmultimediatimer.aspx

1 голос
/ 02 ноября 2011

Вы можете использовать таймер высокого разрешения, но он зависит от устройства.Вам придется запросить его.См. Эту страницу MSDN для объяснения: http://msdn.microsoft.com/en-us/library/aa964692%28v=vs.80%29.aspx

Но System.Diagnostics.Stopwatch должно дать вам точность около 1 мс.

0 голосов
/ 20 марта 2018

Я понятия не имею, как сделать что-то подобное в современной версии Windows - просто наткнулся на этот старый вопрос и вспомнил, что я столкнулся с подобной проблемой еще давным-давно ...

Вернувшись в каменный век (Win 3.11 и позже Win95), я смог получить очень высокую и воспроизводимую производительность в реальном времени (10 кГц не было проблемой, джиттер также был довольно приличным - в микросекундном диапазоне на 90 МГц Pentium) перепрограммируя прерывание в реальном времени и подключаясь к немаскируемому прерыванию таймера. В то время это включало VxD (драйвер виртуального устройства) для прямого доступа к таймеру. Также необходимо получить выделенное пространство совместно используемой памяти и код в сборке (возможно, можно смешивать сборку с C / C ++ - очевидно, чем выше частота, тем плотнее должен быть цикл).

По сути, я сократил период таймера до желаемого, затем выполнил свой код - он периодически перезванивал в ОС, чтобы ОС выдерживала ожидаемый интервал. Также нужно было перехватить функции, которые ОС использовала для настройки интервала и соответственно отрегулировать мои обратные вызовы (при условии, что мой код всегда работал с более высокой частотой, чем требовала ОС). На самом деле использовал его для управления движением через порт принтера. Никогда не делал это в выпущенном программном обеспечении, но действительно запустил базовую версию ЧПУ.

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

Я бы начал с изучения программирования драйверов устройств и, возможно, игр (например, Direct X), пытаясь получить какой-либо тип производительности ОСРВ вне выделенной среды ОСРВ.

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