Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Системное программирование и WinAPI > Ожидаемый таймер


Автор: IGanja 8.6.2012, 15:37
Таймер срабатывает каждую секунду. Выполняется итерация цикла и оставшееся время от секунды жду освобождения таймера. Все хорошо пока не случается превышения секунды в работе кода итерации. По моим представлениям после превышения, например при работе 2,8 секунды на строчке WaitForSingleObject(hTimer, INFINITE);  программа должна дожидаться начала следующий секунды, ведь таймер занят. Вреальности же проскакивает коротенькая итерация на 0,2 секунды и далее таймер входит в свою требуемую частоту. Может кто ни будь знает почему так происходит? У Рихтера на этот счет ничего нет.

Код

    while(!stop)
    {
        QueryPerformanceCounter(&Start);

                count++;
        leg += 1;
        leg %= 16;
        printf("InnerLeg %d\n",leg);

        if(count == 7)
        {
            while(Time<2.8f)
            {
                QueryPerformanceCounter(&Stop1);
                Time = (double)(Stop1.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; 
            }
            printf(" %f\n",Time);
        }
        else
        {
            QueryPerformanceCounter(&Stop1);
            Time = (double)(Stop1.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; 
            printf(" %f\n",Time);
        }

        // жду следующего лега
        WaitForSingleObject(hTimer, INFINITE); 

        QueryPerformanceCounter(&Stop2);
        Time = (double)(Stop2.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; 
        printf(" %f\n",Time);
    }


Добавлено через 10 минут и 1 секунду
вот полностью рабочая прога

Код

#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <conio.h>

float FREQUENCY = 1    ; //Гц
int leg = 0; //позиция в 16 ричной решетке

int main(void)
{
    int i=0,j=0;
    int count=0;
    char stop =0;
    char oneIter =0;
    LARGE_INTEGER Start, Stop1, Stop2, Freq;
    LARGE_INTEGER firstStart;
    const int unitPerSecond = 10000000; //10 миллионов интервалов по 100 нано секунд = 1 секунд
    int freq_ms = 1000/FREQUENCY; //msec
    DWORD dwThreadId; 
    HANDLE hTimer = NULL;
    double Time=0;

    SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); // установка приоритета процесса

    // создание и настройка таймера
    firstStart.QuadPart = -(unitPerSecond/FREQUENCY); // первое срабатывание таймера
    hTimer = CreateWaitableTimer(NULL, FALSE, NULL); // таймер с автосбросом
    SetWaitableTimer(hTimer, &firstStart, freq_ms, NULL, NULL, FALSE); // настройка

    QueryPerformanceFrequency(&Freq); // tick/sec

    while(!stop)
    {
        QueryPerformanceCounter(&Start);

        count++;

        leg += 1;
        leg %= 16;
        printf("InnerLeg %d\n",leg);

        if(count == 7)
        {
            while(Time<2.8f)
            {
                QueryPerformanceCounter(&Stop1);
                Time = (double)(Stop1.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; //ms;
            }
            printf(" %f\n",Time);
        }
        else
        {
            QueryPerformanceCounter(&Stop1);
            Time = (double)(Stop1.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; //ms;
            printf(" %f\n",Time);
        }

        // жду следующего лега
        WaitForSingleObject(hTimer, INFINITE); 

        QueryPerformanceCounter(&Stop2);
        Time = (double)(Stop2.QuadPart - Start.QuadPart)/(double)Freq.QuadPart; //ms;
        printf(" %f\n",Time);
    }


    printf( "game over\n" );
    getch();

    return 0;
}

Автор: feodorv 8.6.2012, 21:07
Цитата(IGanja @  8.6.2012,  16:37 Найти цитируемый пост)
программа должна дожидаться начала следующий секунды, ведь таймер занят.

Почему он занят? Потому что с автосбросом? Но ведь автосброс сработает только в момент вызова WaitForSingleObject. Так сделано специально, чтобы не потерялось пропущенное срабатывание таймера. Оно и не теряется.

Поскольку Вы ожидаете только срабатывание таймера, то можно его просто сэмулировать через GetTickCount и Sleep.
А можно в существующей схеме просто проверять, что пропущен тик таймера, и уже дожидаться следующего тика.

Автор: IGanja 9.6.2012, 13:53
feodorv, то есть, таймер через секунду освобождается и снова перейдет в занятое состояние только после вызова WaitForSingleObject? Тогда все понятно. Спасибо.

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

Автор: feodorv 9.6.2012, 19:34
Цитата(IGanja @  9.6.2012,  14:53 Найти цитируемый пост)
feodorv, то есть, таймер через секунду освобождается и снова перейдет в занятое состояние только после вызова WaitForSingleObject? 

 smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)