Как запустить функцию С++ с точным интервалом в миллисекунды

Мне нужно найти способ инициировать выполнение функции C++ в точные миллисекундные периоды.

Мне нужно воспроизвести цикл и запустить функцию каждые 40 мс или меньше. Но для простоты остановимся на 40 мс. Пробовал поставить Sleep(40), но метод срабатывает не в определенный момент времени.

Мне просто интересно, есть ли другой способ синхронизации действий, кроме Sleep() в бесконечном цикле while.

Я пытался даже воспроизвести луп на максимальной скорости (процессор ушел на 20%) и замерить разницу системного времени. Затем запуск действия по прошествии 40 мс.

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

Цикл работает в потоке.

Я пытался дать больший приоритет потоку, но безуспешно.

Дополнительная информация

Сервер работает на операционной системе Windows 7.


person Patrik    schedule 10.11.2013    source источник
comment
На этот вопрос уже был дан ответ в [Вопросах и ответах] [1]. [1]. а>   -  person goldcode    schedule 11.11.2013
comment
Можете ли вы дать немного больше информации об окружающей среде (операционная система, оборудование и т. д.)? и точная причина, по которой вам нужно что-то, что выполняется каждые 40 мс?   -  person tigrou    schedule 11.11.2013
comment
Мне нужно воспроизвести фильм в проигрывателе XBMC, который должен отправлять данные на сервер с определенной частотой кадров. Таким образом, 25 кадров в секунду = 40 мс каждый кадр. Сервер должен отправлять некоторые значения на некоторое оборудование в определенное время и должен быть синхронизирован. Все работает на ОС Windows. Так что, к сожалению, нет ОС реального времени.   -  person Patrik    schedule 11.11.2013
comment
Тогда вы уже знаете ответ, вы делаете это неправильно. Надежная частота кадров требуется только в программе, которая отображает видео. Совершенно неважно, какие случайные задержки возникают выше по течению от этого, требуется только буферизация.   -  person Hans Passant    schedule 11.11.2013


Ответы (1)


Вы можете отслеживать время с помощью такой функции, как timeGetTime:

void main()
{
    unsigned int last_call_time = timeGetTime();

    while(true)
    {
        do_something_else();

        unsigned int now_time = timeGetTime();
        if(now_time > (last_call_time + 40))
        {
            call_time_critical_function();
            last_call_time = timeGetTime();//last time is re initialized
        }
    }
}

timeGetTime — это стандартная функция Windows, которая отслеживает время в миллисекундах. Если функция недостаточно точна, вам придется использовать что-то, что может отслеживать наносекунды, например QueryPerformanceCounter, и в Интернете есть множество примеров использования этой функции.

person Raxvan    schedule 10.11.2013
comment
Я бы порекомендовал поместить некоторую минимальную usleep() или другую функцию блокировки по времени внутри цикла while, вместо того, чтобы делать такое занятое (плотно потребляющее ЦП) ожидание. - person πάντα ῥεῖ; 11.11.2013
comment
Это не учитывает время, необходимое для выполнения критической функции. Если эта функция различается по продолжительности, вы не получите правильный интервал. - person Jerry Jeremiah; 11.11.2013
comment
Я не очень разбираюсь в мультимедийном программировании для Windows, но правильный ли это выбор - цикл опроса?! - person usr; 11.11.2013
comment
На самом деле нужно спать до следующего времени обратного вызова (например, usleep(max(0, last_call_time+40-timeGetTime())); - person Jeremy Friesner; 11.11.2013
comment
В яблочко. Независимо от того, как я пытаюсь, сон длится 40 мс, 41 мс, 42, 43 мс ... и вы никогда не знаете, сколько. - person Patrik; 11.11.2013
comment
@Jerry Jeremiah да, это простой пример, иллюстрирующий использование timeGetTime(). - person Raxvan; 11.11.2013
comment
Функция @Patrik Sleep (я не уверен в usleep) отключит текущий поток от ЦП, и время будет очень сложным, поскольку потоку может потребоваться время, чтобы снова начать выполнение. Если время имеет решающее значение, вы должны использовать QueryPerformanceCounter внутри цикла и отслеживать время вручную. - person Raxvan; 11.11.2013