Является ли System.Drawing слишком медленным для того, что мы хотим сделать? - PullRequest
3 голосов
/ 10 ноября 2010

В настоящее время я работаю над пользовательским интерфейсом приложения для создания форм. Основное окно - это форма без полей, площадь поверхности которой почти полностью отображается в событии Form.Paint. Задний буфер создается и рисуется довольно условно:

private void form_Paint(object sender, PaintEventArgs e) {
  e.Graphics.DrawImage(BackBuffer, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel);
}

Некоторые области заднего буфера перерисовываются при различных условиях; эффекты наведения мыши довольно распространены. Класс, который выполняет перерисовку, делает недействительными только применимые области. Несмотря на это, достаточно просто провести мышью по форме, чтобы запустить высокопроизводительный процессор до> 50% использования в течение нескольких секунд.

Я профилировал приложение, и более 80% процессорного времени расходуется при вызове DrawImage выше. Я знал, что GDI + работает медленно и не использует (мало?) Графического процессора ... и целевая платформа для приложения не дает никаких гарантий, что графический процессор не будет интегрирован в первую очередь. Но я понятия не имел, что это так плохо.

Должен ли я столкнуться с тем фактом, что GDI + просто недостаточно быстр для того, что мы хотим сделать, или все же есть возможность улучшить код?

-edit-

BackBuffer представляет собой растровое изображение, которое создается во время запуска системы. Его размер соответствует разрешению экрана. Различные области рисуются на нем во время различных событий, таких как наведение мыши и щелчки. Создано достаточно просто:

this.BufferBmp = new Bitmap(screenWidth, screenHeight);
this.Gfx = Graphics.FromImage(BufferBmp);

Gfx.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit;

Ответы [ 3 ]

3 голосов
/ 10 ноября 2010

Создание собственного «обратного буфера» вместо использования встроенной поддержки двойной буферизации очень сложно получить.Для great важен формат буфера в пикселях.На любом современном компьютере, который я пробовал в любом случае, формат 32bppPArgb в десять раз быстрее, чем на любом другом.Воспользуйтесь встроенной поддержкой двойной буферизации для превосходной производительности.

Еще одна возможная потеря - ваша попытка сохранить область отсечения как можно меньше.Это может быть байт, когда регион становится сложным.Похоже, вы близки к этому, если позволить быстрому движению мыши генерировать небольшие прямоугольные области обновления.Когда рисунок отстает, это почти всегда происходит, так как мышь получает более высокий приоритет, вы можете создать довольно сложную цепочку из маленьких прямоугольников.Сначала проверьте это, просто сделав недействительной всю область.Следующий подход заключается в том, чтобы расширить область самостоятельно, всегда сохраняя ее одним прямоугольником.Сбросьте это при запуске OnPaint.

3 голосов
/ 10 ноября 2010

GDI + может быть очень хорошим, если вы относитесь к нему правильно.Я бы предложил профилировать код рисования с помощью чего-то вроде Муравьи RedGate , но есть несколько других практических правил, на которые вы можете обратить внимание для повышения производительности:

  • Используйте объект Graphics, переданный вСобытие OnDraw, не создавайте свои собственные
  • Используйте области отсечения, чтобы минимизировать область, которую необходимо перерисовать
  • Создавайте объекты рисования, такие как кисти, шрифты и ручки, в области видимости класса (невоссоздавать каждый раз)
  • Избегайте слишком большого количества вызовов методов, происходящих из метода OnDraw
  • Избегайте слишком большого создания объектов на этапе рисования
  • Блоки try / catch влияют на производительность
  • Может использовать GDI вместо GDI + (см. Ссылку ниже)

Также есть возможность сделать BitBlt вместо этого.Смотрите здесь аналогичный вопрос и решение .

1 голос
/ 10 ноября 2010

Я думаю, что вы хотите создать новый класс, который наследуется от Form, а затем выполнить рисование в методе OnPaint, а не прослушивать событие Paint из формы.

...