Класс C++ - Атрибут увеличения и уменьшения каждые N миллисекунд

Это, должно быть, простой вопрос, но я не могу найти правильный ответ на него.

Я пишу на VS-C++. У меня есть собственный класс "Персона" с атрибутом "высота". Я хочу вызвать метод класса Grow(), который запускает таймер, который будет увеличивать атрибут 'height' каждые 0,5 секунды.

У меня будет StopGrow(), который останавливает таймер, и Shrink(), который уменьшается вместо увеличения.

Мне действительно нужно немного нажать на то, какой таймер использовать и как использовать его в методе Grow(). Другие методы должны быть понятны после того, как вы это узнаете.

Это мой первый вопрос, поэтому, пожалуйста, будьте добры (и предупредите меня, если я делаю это неправильно:) Прости мой английский, а не мой родной язык.

5 ответов

Решение

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

Не открывайте элемент высоты, но используйте метод, такой как GetHeight(), который вычислит высоту в тот момент, когда вам это нужно.

Ваш метод Grow() установит базовое значение высоты, время начала и ничего больше. Затем ваш метод GetHeight () вычтет начальное время из текущего времени, чтобы вычислить высоту "прямо сейчас", когда вам это нужно.

Таймеры не нужны!

Поскольку вы работаете в Windows, возможно, самое простое решение - использовать функцию GetTickCount(), предоставляемую Windows.

В языке C++ нет хорошей функции таймера, точность которой гарантированно меньше секунды.

Поэтому вместо этого включите windows.h заголовок, а затем позвоните GetTickCount() чтобы получить количество миллисекунд. При следующем вызове вы просто вычтете два значения, и если результат превысит 500, полсекунды истекли.

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

Возможно, вы захотите взглянуть на CreateTimerQueue() а также CreateTimerQueueTimer(), Я никогда не использовал их лично, но они, вероятно, соответствовали бы требованиям.

В настоящее время я создаю поток, который отвечает за выполнение операций на основе таймера. Это вызывает WaitForSingleObject() на событии ручного сброса с тайм-аутом 10 мс. Он хранит внутреннюю коллекцию обратных вызовов в форме указателя на метод и объектов, для которых вызываются обратные вызовы. Все это скрыто за синглтоном, который предоставляет интерфейс планировщика, который позволяет вызывающему методу вызывать методы для объектов после истечения таймера или регулярно через интервал. Похоже, что две функции, которые я упомянул, должны дать вам почти одинаковую функциональность... хммм... может быть, пришло время пересмотреть этот код планировщика...;-)

Sleep() и обычное событие таймера запускаются с 10 мсек.
Для событий таймера высокого разрешения на окнах используйте таймеры высокого разрешения

Вопрос не из легких! У вас есть как минимум две возможности:

  • создайте поток, который будет выполнять цикл: сон 0,5 с, увеличение высоты, сон 0,5 с, увеличение высоты и т. д.
  • инвертируйте поток управления и передавайте его какой-то платформе, такой как Boost::Asio, которая будет вызывать ваш обработчик таймера каждые 0,5 с.

Для того, чтобы принять правильное решение, вы должны подумать о всей вашей заявке. Это вычисляет что-то (тогда возможно потоки)? Взаимодействует ли он с пользователем (тогда, возможно, управляемым событиями)? Каждый подход имеет несколько ошибок:

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