2010-08-20 1 views
15

У меня есть приложение, которое делает лот рисунка, давайте притворимся, что это приложение, подобное Viso. Он имеет объекты, которые имеют несколько суб-объекты, которые нарисованы, вещи могут быть связаны, изменять размер и т.д. В настоящее время, когда я звоню краску на определенном подъобекта или объекта, я делаю следующее:Должен ли я создавать новые Pens/Brushes для запроса краски или хранить их на протяжении всего жизненного цикла приложения?

using(var pen = new Pen(this.ForeColor)) 
{ 
    // Paint for this object. 
} 

Я прочитайте противоречивые ответы, что это должно быть сделано для приложения, которое постоянно рисует одно и то же (может быть, просто изменено, перемещено и т. д.). Должен ли я хранить Pen/Brush с объектом, а затем удалять их все, когда приложение будет удалено, или они достаточно эффективны для создания/размещения для каждого вызова (помня, что это приложение с интенсивной графикой).

EDIT: Есть уже два ответа, которые имеют противоречивые ответы, и именно здесь я не уверен, чтобы сделать переключатель. У кого-нибудь есть статистика по поводу различий?

ответ

9

Конечно, вы можете использовать классы Pens and Brushes, которые предоставляют вам объекты, которые уже созданы средой выполнения.

Например, если вы хотите один из стандартных цветов Pens, вы можете сделать это:

var pen = Pens.Red; 

Аналогично вы можете сделать то же самое с Brushes, если вы просто хотите, стандартные твердые кисти цветов:

var brush = Brushes.Red 

Используя их, вам не нужно беспокоиться об их очистке, утилизации или иным способом.

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

EDIT:

Чтобы создать и распоряжаться массив 100000 новых ручек занял примерно полсекунды на моей древней старой XP машине, работает тест приложение в режиме отладки.

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

+0

Да, все ручки/кисти имеют разные цвета, чем предопределенные цвета. – TheCloudlessSky

+0

ОК, справедливо. См. Редактирование на мой пост. – Andy

+0

Я только что провел некоторое тестирование, прежде чем проверять ваш пост, и вы правы, это безумно быстро создать/распорядиться. В этом случае оптимизация не нужна. Благодаря! – TheCloudlessSky

1

Повторное использование таких же Pen и Brush в операциях, которые потребуют от него много раз, будет намного быстрее, чем утилизация их каждый раз с помощью using.

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

+1

У вас не было бы никаких доказательств относительно * как * гораздо быстрее? Я не хочу делать оптимизацию, если это не очень важно. – TheCloudlessSky

0

Да, лучше всего протестировать, как предлагает @fantius, вы, вероятно, обнаружите, что это не имеет значения - хотя мне бы хотелось, чтобы они открылись, как будто я правильно помню, что они неуправляемые ресурсы и могут использовать ваши Память. Если вы каждый раз воссоздавали их, вам нужно быть особенно осторожным, чтобы правильно их утилизировать, чтобы избежать утечек памяти.

+0

При каждом повторном их создании они располагаются с инструкцией 'using'. – TheCloudlessSky

3

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

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

Если вы используете относительно немного разных цветов, но много объектов используют каждый цвет, вы можете не захотеть, чтобы каждый объект держался за его собственную ручку. Создайте класс кеша, который держит Dictionary<Color,Pen> и передает их через PenCache.GetPen(ForeColor). Как и при использовании Pens.Black, вы можете забыть об утилизации. Проблема возникает, если вы кратко используете цвет, а затем не нуждаетесь в нем снова. Пен получил кеширование, так что вы застряли с ним в памяти навсегда. Вместо этого вы можете сохранить Dictionary<Color,WeakReference<Pen>>, позволяя кэшированным ручкам в конечном итоге собирать мусор, если они больше не нужны.

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

+0

+1, так как мне очень нравится идея использования 'WeafReference'. Мне нужно будет больше узнать об этом для другого проекта. Я нашел через некоторое тестирование, что создание/удаление ручек/кистей довольно эффективно, поэтому я принял ответ Энди. – TheCloudlessSky

+0

Я не знаю, стоит ли боль. На самом деле у Пера есть черты вариантов не только обычного цвета. Ширина, Кисть, Стиль, Шаблоны, Кол. Если вам нужно все это, это будет боль – GorillaApe

Смежные вопросы

 Смежные вопросы