Какой самый чистый способ создать тайм-аут для цикла while? - PullRequest
7 голосов
/ 26 января 2010

Windows API / C / C ++

1. ....  
2. ....
3. ....    
4.    while (flag1 != flag2)
5.    {
6.      SleepEx(100,FALSE);   
        //waiting for flags to be equal (flags are set from another thread).
7.    }
8. .....
9. .....  

Если флаги не совпадают друг с другом через 7 секунд, я бы хотел продолжить к строке 8.

Любая помощь приветствуется. Спасибо.

Ответы [ 7 ]

10 голосов
/ 26 января 2010

Если вы ожидаете, когда будет установлен определенный флаг или будет достигнуто время, гораздо более чистым решением может быть использование события автоматического / ручного сброса. Они предназначены для сигнализации условий между потоками и имеют очень богатый API, разработанный поверх них. Например, вы могли бы использовать API WaitForMultipleObjects, который принимает явное значение времени ожидания.

6 голосов
/ 26 января 2010

Не опрашивать для изменения флагов. Даже в режиме сна или выхода во время цикла это просто тратит время процессора.

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

Например:

Thread1:

 flag1 = foo;
 SetEvent(hEvent);


 Thread2:

 DWORD timeOutTotal = 7000;  // 7 second timeout to start.
 while (flag1 != flag2 && timeOutTotal > 0)
 {
     // Wait for flags to change
     DWORD start = GetTickCount();

     WaitForSingleObject(hEvent, timeOutTotal);

     DWORD end = GetTickCount();

    // Don't let timeOutTotal accidently dip below 0.
    if ((end - start) > timeOutTotal)
    {
        timeOutTotal = 0;
    }
    else
    {
       timeOutTotal -= (end - start);
    }

 }
3 голосов
/ 26 января 2010

Вы не упомянули, что произойдет, если флаги равны.

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

Лучше всего использовать событие и использовать функцию WaitForSingleObject с периодом ожидания 7000 миллисекунд.

3 голосов
/ 26 января 2010

Вы можете использовать QueryPerformanceCounter из WinAPI. Проверьте это до того, как запустится время, и запросите, прошло ли количество времени. Тем не менее, это таймер высокого разрешения. Для более низкого разрешения используйте GetTickCount (миллисекунды).

Все зависит от того, активно ли вы ждете (что-то делаете) или пассивно ожидаете внешнего процесса. Если последнее, то следующий код с использованием Sleep будет намного проще:

int count = 0;
while ( flag1 != flag2 && count < 700 )
{
   Sleep( 10 ); // wait 10ms
   ++count;
}

Если вы не используете Sleep (или Yield) и ваше приложение постоянно проверяет состояние, то вы будете раздувать процессор, на котором работает приложение.

Если вы широко используете WinAPI, вам следует попробовать более нативное решение, читайте о функциях синхронизации WinAPI .

2 голосов
/ 26 января 2010

Убедитесь, что вы внесли туда sleep() или yield(), иначе вы съедите весь ожидающий процессор (или ядро).

1 голос
/ 26 января 2010

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

0 голосов
/ 26 января 2010

Если ваше приложение выполняет некоторые сетевые функции, взгляните на вызов POSIX select (), особенно на функцию тайм-аута!

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