Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Каков наилучший способ выйти из цикла по истечении 30 мс на С++?

Автор вопроса: Neil GОтветов: 9

Каков наилучший способ выйти из цикла как можно ближе к 30 мс в С++. Ускорение опроса: microsec_clock ? Опрос QTime ? Что-то другое?

Что-то типа:

A = now;
for (blah; blah; blah) {
    Blah();
    if (now - A > 30000)
         break;
}

Он должен работать в Linux, OS X и Windows.

Вычисления в цикле предназначены для обновления симуляции. Каждые 30 мс я хотел бы обновить область просмотра.

  • добавил тег qt к вашему вопросу, как вы упомянули QTime Idan K 03.06.2009
  • Вы имеете в виду любое время после 30 мс или как можно ближе к 30 мс? Max Lybbert 03.06.2009
  • Может быть, это поможет рассказать, чего вы действительно хотите достичь. lothar 03.06.2009
  • Возможно, вы также захотите добавить, какое оборудование/ОС вы используете. Различные аппаратные платформы предоставляют счетчики времени с разной точностью. J. Polfer 03.06.2009
  • Ответил на комментарии в вопросе. Neil G 03.06.2009
  • Спасибо всем за отличные ответы! Для этого существует StackOverflow. Три верхних ответа - это все решения: используйте clock(), используйте потоки и опрашивайте аппаратные часы. Первое решение требует наименьшей работы и является моим временным решением, пока я не разработаю многопоточную модель. (Удивительно, но никто не говорил о boost::microsec_timer или как там это называется.) Neil G 04.06.2009

c++timerqtclock

Ответы

Ответ 1 · рейтинг 2 · K M

Пример фрагмента кода в этой ссылке в значительной степени делает то, что вы хотите:

http://www.cplusplus.com/reference/clibrary/ctime/clock/

Адаптировано из их примера:

void runwait ( int seconds )
{
   clock_t endwait;
   endwait = clock () + seconds * CLOCKS_PER_SEC ;
   while (clock() < endwait)
   {
      /* Do stuff while waiting */
   }
}

Ответ 2 · рейтинг 11 · Juliano

Вычисления в цикле предназначены для обновления симуляции. Каждые 30 мс я хотел бы обновить окно просмотра.

Рассматривали ли вы использование потоков? То, что вы описываете, кажется прекрасным примером того, почему вы должны использовать потоки вместо таймеров.

Основной поток процесса продолжает заботиться о пользовательском интерфейсе и имеет QTimer, установленный на 30 мс, для его обновления. Он блокирует QMutex для доступа к данным, выполняет обновление и освобождает мьютекс.

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

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

Ответ 3 · рейтинг 4 · Ariya Hidayat

Хотя это не отвечает на вопрос, это может дать другой взгляд на решение. Как насчет размещения кода моделирования и пользовательского интерфейса в разных потоках? Если вы используете Qt, периодическое обновление можно реализовать с помощью таймера или даже QThread::msleep( )а>. Вы можете адаптировать пример Мандельброта с резьбой в соответствии со своими потребностями.

Ответ 4 · рейтинг 2 · SingleNegationElimination

Если вам нужно выполнить работу до истечения определенного времени, тогда ответ docflabby точен. Однако, если вам нужно просто подождать, ничего не делая, пока не истечет указанное время, вам следует использовать usleep()

Ответ 5 · рейтинг 2 · James

Короткий ответ: в общем случае вы не можете, но можете, если работаете на правильной ОС или на правильном оборудовании.

Вы можете получить БЛИЗКО 30 мс на всех ОС, используя вызов сборки в системах Intel и что-то еще в других архитектурах. Я откопаю ссылку и отредактирую ответ, чтобы включить код, когда найду его.

Проблема заключается в алгоритме разделения времени и в том, насколько близко вы находитесь к концу своего временного отрезка в многозадачной ОС.

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

редактировать: ЛОЛ! Кто-то уже опубликовал аналогичный фрагмент на SO: Функция таймера для предоставления времени в наносекундах с использованием C++

У VonC есть комментарий с ассемблерным кодом процессорного таймера.

Ответ 6 · рейтинг 2 · J. Polfer

Согласно вашему вопросу, каждые 30 мс вы хотите обновлять окно просмотра. Однажды я написал похожее приложение, которое проверяло оборудование каждые 500 мс на наличие похожих вещей. Хотя это не дает прямого ответа на ваш вопрос, у меня есть следующие дополнения:

  • Вы уверены, что Blah() для обновления области просмотра может выполняться менее чем за 30 мс в каждом экземпляре?
  • Больше похоже на то, что запуск Blah() будет лучше выполняться обратным вызовом таймера.
  • Очень сложно найти библиотечный объект таймера, который будет устанавливать интервал в 30 мс для выполнения обновлений в графическом фреймворке. В Windows XP я обнаружил, что стандартный API-таймер Win32, который отправляет оконные сообщения по истечении интервала таймера, даже на 2-ГГц P4, не может выполнять обновления быстрее, чем с интервалом 300 мс, независимо от того, насколько малый интервал времени я установил на таймер. Хотя в Win32 API были доступны высокопроизводительные таймеры, у них есть много ограничений, а именно то, что вы не можете выполнять какие-либо IPC (например, виджеты обновления пользовательского интерфейса) в цикле, подобном тому, который вы указали выше.
  • По сути, в результате вы должны очень тщательно спланировать, как вы хотите, чтобы обновления происходили. Возможно, вам придется использовать потоки и посмотреть, как вы хотите обновить область просмотра.

Просто есть о чем подумать. Они застали меня врасплох, когда я работал над своим проектом. Если вы уже обдумали эти вещи, пожалуйста, не обращайте внимания на мой ответ :0).

Ответ 7 · рейтинг 2 · Community

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

Ответ 8 · gatorfax

См. QueryPerformanceCounter и QueryPerformanceFrequency.

Ответ 9 · swongu

Если вы используете Qt, вот простой способ сделать это:

QTimer* t = new QTimer( parent ) ;
t->setInterval( 30 ) ; // in msec
t->setSingleShot( false ) ;
connect( t, SIGNAL( timeout() ), viewPort, SLOT( redraw() ) ) ;

Вам нужно указать viewPort и redraw(). Затем запустите таймер с помощью t->start().

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы