У меня есть форма с изображением, в котором отображается изображение и какое-то наложение, нарисованное в обработчике событий Paint на картинке. Оверлей обновляет itslef (в основном изменяет непрозрачность различных частей наложения) на основе движения мыши.
В настоящее время я вызываю pictureBox.Invalidate()
из обработчика с перемещением мыши, чтобы обеспечить перерисовку оверлея. Я также внедрил некоторую логику, чтобы определить, действительно ли требуется перерисовка - если ни один объект не изменил свою непрозрачность при перемещении мыши, PictureBox
не является недействительным.
Я все еще получаю 50-процентное использование процессора на двухъядерной машине, когда я перемещаю мышь быстрее, чем очень медленно. Я предполагаю, что рутина рисования просто не удается перерисовать так часто, как мышь перемещаются события.
Нарисовано не так много объектов, до 10 заполненных прямоугольников с четырьмя заполненными треугольными углами. Проблема в том, что уже существует один объект оверлея. В основном для выполнения рисунка используются только методы FillRectangle
и FillArea
.
Какой подход вы предложили бы в этой ситуации для предотвращения такого высокого использования ЦП?
Хорошо, для начала подумайте, как часто вам действительно нужно перерисовывать, чтобы получить эффект, который вы ищете. Прямо сейчас, вы перерисовываетесь в ответ на события мыши, но их может быть намного больше, чем вы могли бы подумать, и вам, вероятно, не нужно перерисовывать для каждого из них. Покраска (в ответ на Invalidate()) по большей части является низкоприоритетной, но это просто означает, что вы в конечном итоге будете использовать любой запасной процессор для этого - лучше, если вы будете отслеживать время, которое вы последний раз перекрасили, и избегайте делать это снова слишком рано.
Использование таймера для исправления частоты обновления при некоторой константе (начало с задержкой 40 мс при частоте обновления примерно 25 Гц и увеличение или уменьшение по мере необходимости) - это простой способ сделать это... Таймеры (System.Windows. Forms.Timer как минимум) также являются низкоприоритетными, поэтому вам не нужно беспокоиться о том, что ваша логика обновления вытесняет более важные обработчики событий.
Конечно, сохраните существующий код, который вы используете, чтобы определить, действительно ли что-либо изменилось. Установите флаг, когда он это делает, и когда этот флаг не установлен, просто ничего не делайте в обработчике событий таймера.
При этом вы должны увидеть немедленное уменьшение максимального времени обработки, так как вы отделите частоту обновления от скорости мыши. Вы также обнаружите, что у вас больше контроля над средним временем обработки, так как частота обновления находится под вашим контролем: слишком высокая, уменьшает скорость таймера; не достаточно гладко, увеличить его!
Ограничьте циклы вытягивания.
Например, в игровом программировании типичная частота кадров составляет 30-60fps
или от тридцати до шестидесяти кадров в секунду. Это означает, что экран рисуется от 30-60 раз в секунду. Примените какой-то предел для своего приложения. 12fps
- это примерно самая низкая частота кадров, которую человеческий глаз обманывает в веру, - это анимация, поэтому я бы не стал ниже этого.
На движениях мыши кажется неправильным быть честным. Например, спам мыши быстро увеличит скорость вытягивания.
Если вы перерисовываете событие с перемещением мыши, вы будете многократно перерисовывать. Вопрос в том, действительно ли вам это нужно рисовать каждый раз, когда мышь действительно перемещается, или вы хотите, чтобы она рисовала, когда она закончила движение? Или где-то посередине? Добавьте некоторую логику, которая только перерисовывается в конце движения мыши или что-то в этом роде.