C ++ использовать поток в качестве таймера - PullRequest
2 голосов
/ 18 июля 2011

У меня есть проект с другим потоком, который делает некоторые вещи.

Все нормально, но я бы хотел, чтобы некоторые функции вызывались каждые 20 мс (например), но с учетом времени, потраченного на функцию ..Я пытаюсь объяснить лучше ... Я вызываю функцию, и функция тратит 6 мс, чтобы выйти, поэтому я хочу, чтобы поток спал 14 мс (20 - 6), при следующем вызове функция потратила 12 мс, поэтомусон будет только 8 мс .... как я могу это сделать?вот мой код:

// thread constructor
DWORD dwThreadId, dwThrdParam = 1;  
HANDLE thread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)workerFunc, &dwThrdParam, 0, &dwThreadId );

// thread function
DWORD WINAPI workerFunc( LPDWORD lpdwParam )
{
    while( true )
    {
        myFunction( );
        Sleep( ??? );
    }
    return 0;
}

спасибо!

Ответы [ 4 ]

2 голосов
/ 18 июля 2011

Что по этому поводу:

clock_t start, end;
while( true )
{
    start = clock();
    myFunction( );
    end = clock();
    Sleep(20-(end-start)*CLOCKS_PER_SEC/1000.0);
}
2 голосов
/ 18 июля 2011

Простой подход состоит в том, чтобы отправить поток в спящий режим на переменное время:

void periodic_function()
{
  /* function body */

  timestamp = get_time(); // pseudo-function
  remaining_sleep_time = std::min(0, 20 - (timestamp - last_timestamp));
  last_timestamp = timestamp;
  milli_sleep_callback(remaining_sleep_time, periodic_function);
}

Вам понадобится подходящая постоянная функция часов для get_time() и функция сна - попробуйте<chrono> или <tr1/chrono> заголовок.В этом примере я предположил, что у вас есть обратный вызов таймера (как в boost.ASIO), но вы также можете сделать бесконечный цикл или что-то в этом роде.

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

1 голос
/ 18 июля 2011

Используйте GetTickCount до вызова myFunc и после вызова myFunc.Разница дает вам время, проведенное в myFunc.Обратите внимание, что это время включает время, затраченное процессом из-за планирования ОС.

0 голосов
/ 20 августа 2011

Если вам нужна точность, используйте NtSetTimerResolution при запуске программы для установки разрешения таймера. Да, это недокументированная функция, но хорошо работает. Вы также можете использовать NtQueryTimerResolution для определения разрешения по таймеру (перед настройкой и после установки нового разрешения, чтобы быть уверенным).

Вам необходимо динамически получить адрес этих функций, используя GetProcAddress из NTDLL.DLL, так как он не объявлен в заголовке или любом файле LIB.

Установка разрешения таймера таким образом повлияет на Sleep, таймеры Windows, функции, которые возвращают текущее время и т. Д.

...