Страница: 1 |
|
Вопрос: Работа с Label
|
Добавлено: 10.07.08 13:07
|
|
Автор вопроса: vbSerGanT
|
Встретил недавно такую проблему.
Хотел сделать тень у надписи, а прозрачность не устанавливается. Имеется ввиду метка под меткой на некотором смещении и другим цветом.
Ответить
|
Номер ответа: 4 Автор ответа: BG(Алексей)
Вопросов: 26 Ответов: 295
|
Профиль | | #4
|
Добавлено: 20.07.08 05:56
|
Private Sub Label1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Label1.Paint
  im Br = New SolidBrush(Color.FromArgb(70, Me.Label1.ForeColor))
  im shadowrect As Rectangle = Me.ClientRectangle
shadowrect.X += 5
shadowrect.Y += 5
e.Graphics.DrawString(Me.Label1.Text, Me.Label1.Font, Br, shadowrect)
End Sub
Ответить
|
Номер ответа: 6 Автор ответа: BG(Алексей)
Вопросов: 26 Ответов: 295
|
Профиль | | #6
|
Добавлено: 20.07.08 19:17
|
А Dispose Пушкин вызывать будет?
Нет не Пушкин, GC.
Да и зачем платить дважды одну цену?
Переменная обьявлена на уровне процедуры, вот и жить она будет во время работы процедуры. Да и GC сделает это намного правильней.
В качестве теста приведу пример.
Написал я недавно прогрессбар в котором, использовалось много графических обьектов. Естественно я их диспосил.
Отправил я этот прогрессбар своему авторитетному Сенсею на проверку, дабы он взглянул на мои ошибки.
Его приговор меня шокировал. Он сказал, что бы я повыносил все графичекские обьекты из процедур и убрал все диспос методы, переопределил Finalize, а так же ознакомился с работой GC.
Я все это проделал и решил протестировать первичный вариант прогрессбара, а затем второй.
Результат первого варианта(с диспосом) был такой:
Запустил я его нон-стоп на 40 мин и следил за памятью.
Оказалось придраться было не к чему.
Запустил второй вариант с теми же условиями, но без диспос метода.
Сдесь результат отличался.
В течении первых 3-4 минут память выросла аж на 10MB.
потом, резко свалилась до начального значения.
В течении вторых 4-5 минут память выросла аж на 8-9MB.
Опять свалилась и на протяжении оставшегося (из отведенного для теста) времени, изменялась максимум на 1-2MB.
Результат работы GC с управляемыми рессурсами просто на высшем уровне, чего не скажешь о неуправляемых рессурсах. Там нужно все диспосить.
Сдесь все хорошо описанно:
http://www.rsdn.ru/article/dotnet/GC.xml
http://dotsite.spb.ru/Publications/Publication137.aspx
http://dotsite.spb.ru/Publications/Publication132.aspx
Ответить
|
Номер ответа: 7 Автор ответа: Artyom
Разработчик
Вопросов: 130 Ответов: 6602
|
Профиль | | #7
|
Добавлено: 20.07.08 20:24
|
Нет не Пушкин, GC.
Да и зачем платить дважды одну цену?
Начинается...
Обрывы сессий не мучают случайно?
Переменная обьявлена на уровне процедуры, вот и жить она будет во время работы процедуры.
Жить объект (не переменная) будет с момента его создания и до того момента как GC выполнит физическое удаление объекта.
Написал я недавно прогрессбар в котором, использовалось много графических обьектов. Естественно я их диспосил.
Отправил я этот прогрессбар своему авторитетному Сенсею на проверку, дабы он взглянул на мои ошибки.
АААА, жесть!! КТО??? КТО ЭТОТ СЕНСЕЙ???
Я могу предположить что как минимум Андерс Хейлсберг или Джеффри Рихтер. Не меньше!
Я все это проделал и решил протестировать первичный вариант прогрессбара, а затем второй.
Результат первого варианта(с диспосом) был такой:
Запустил я его нон-стоп на 40 мин и следил за памятью.
Оказалось придраться было не к чему.
Запустил второй вариант с теми же условиями, но без диспос метода.
Сдесь результат отличался.
В течении первых 3-4 минут память выросла аж на 10MB.
потом, резко свалилась до начального значения.
В течении вторых 4-5 минут память выросла аж на 8-9MB.
Опять свалилась и на протяжении оставшегося (из отведенного для теста) времени, изменялась максимум на 1-2MB.
Что с чем сраниваем? Среднюю температуру по больнице со скоростью движения света в манной каше?
Результат работы GC с управляемыми рессурсами просто на высшем уровне
Это ты мне будешь рассказывать?
чего не скажешь о неуправляемых рессурсах.
А кто тебе сказал что Brush это управляемый ресурс? Пан Рихтер?
Там нужно все диспосить.
Грубо говоря "диспозить" нужно все что имеет метод Dispose.
Вобщем небольшой разбор полетов.
В принципе, предположить что Brush является неуправляемым ресурсом можно и без рефлектора, так как он является объектом GDI+.
Все очень просто, вот что присутствует в конструкторе SolidBrush:
Dim status As Integer = Gdip.GdipCreateSolidFill(Me.color.ToArgb, zero)
GdipCreateSolidFill - это вызов функции из библиотеки gdiplus.dll.
Что происходит в методе Dispose класса Brush:
Gdip.GdipDeleteBrush(New HandleRef(Me, Me.nativeBrush))
Нужно объяснять что это тоже является выходом в unmanaged код?
И пока Dispose вызван не будет, Brush, на которой указывает хендл nativeBrush As IntPtr будет висать в памяти.
Каким образом происходит развитие если Dispose не вызвать.
Да, как ты сказал, объект будет доступен только в пределах процедуры.
Далее (не сразу после выхода из процедуры, разумеется) запускается сборщик мусора, и видит, что есть некий объект, на которой никто не ссылается, и котороый по сути является мусором.
Но также сборщик мусора видит что у объекта определен финализатор, поэтому объект помещается в отдельную очередь на финализацию.
Далее у объекта вызывается финализатор, в финализаторе, раузмеется, принудительно вызовется Dispose (в этом можно убедиться, посмотрев на его код в рефлекторе):
Protected Overrides Sub Finalize()
Try
Me.Dispose(False)
Finally
MyBase.Finalize
End Try
End Sub
В методе Dispose будут освобождены все неуправляемые ресурсы (см выше, я описал как это делается).
И физически объект будет удален только при следующей сборке мусора потому что на него еще имеется ссылка из очереди финализации.
То есть для этого объекта сборка мусора будет проходить дважды.
Что же будет если вызвать .Dispose принудительно?
В этом случае
1) Освободятся unmanaged ресурсы
2) Объект будет удален из очереди финализации (убедиться в этом можно опять же, посмотрев исходный код метода Dispose)
Public Sub Dispose()
Me.Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Останутся только управлемые ресурсы которые будут освобождены при следующей сборке месора, при этом у этого объекта уже не будет вызываться финализатор поскольку он был удален из очереди.
Подытоживая все сказанное.
Если объект реализует IDisposable, то после работы с ним нужно вызвать метод Dispose (или поручить это блоку Using, что более надежно).
Если этого не сделать, Dispose все равно будет вызван автоматически, но намного позже и это будет связано с определенными дополнительными затратами.
Финализатор как правило имеет смысл делать только в сценарии с Disposable-объектом, когда объект работает с неуправляемыми ресурсами.
Если объект оперирует только управляемыми ресурсами то финализатор делать смысла нет - все упралвяемые ресурсы без проблем будут освобождены сборщиком мусора.
Далее медитировать на Рихтера до полного просвещения.
Сдесь все хорошо описанно:
http://www.rsdn.ru/article/dotnet/GC.xml
http://dotsite.spb.ru/Publications/Publication137.aspx
http://dotsite.spb.ru/Publications/Publication132.aspx
Описано может быть и хорошо, но тебе это похоже мало чем помогло...
Ответить
|
Страница: 1 |
Поиск по форуму