2009-04-15 12 views
16

Jestem świadomy, że najlepszą praktyką jest wywołanie Dispose na dowolny obiekt, który implementuje IDisposable, zwłaszcza obiektów, które zawinąć skończonych zasobów, takich jak uchwyty plików, gniazd, GDI uchwyty itpJak ważne jest wyrzucenie czcionki, naprawdę?

Ale biegnę w przypadku gdzie mam obiekt, który ma Czcionkę, i musiałbym ustawić IDisposable za pomocą kilku warstw obiektów i przejrzeć wiele zastosowań, aby upewnić się, że zawsze mam usuniętą czcionkę. I zastanawiam się, czy warto tej złożoności.

Byłoby jedno, gdyby czcionka zawijała HFONT, ponieważ zasoby GDI są globalne. Ale czcionka nie zawija uchwytu GDI; to GDI +, który jest całkowicie oddzielnym systemem i, o ile rozumiem, jest procesem lokalnym, a nie globalnym, takim jak GDI. I w przeciwieństwie do Image, Font nigdy nie trzyma zasobów systemu plików (i tak wiem).

Moje pytanie brzmi: Jaki jest faktyczny koszt wynajęcia czcionki, aby uzyskać śmieci?

Wiem, że wziąłbym mały hit dla finalizatora, ale jeśli liczba "wyciekłych" czcionek jest mała (powiedzmy pół tuzina), to trafienie uczciwie nie byłoby zauważalne. Oprócz finalizatora nie wydaje się to zbytnio różnić od przydzielania średniej wielkości tablicy i pozwalania GC na jej porządkowanie - to tylko pamięć.

Czy są jakieś koszty, których nie jestem świadomy, pozwalając, aby czcionka otrzymywała GCed?

Odpowiedz

5

prosta odpowiedź: jeżeli tylko kilka, to nie. Jeśli to dużo, to tak. Jeśli twoja aplikacja już stresuje śmieciarza, to tak. Posłużyłbym się perfmonem, aby zobaczyć liczbę siedzących obiektów, a liczba awansowała na wyższe pokolenia, a następnie zdecydować.

4

Problem polega na tym, że odśmiecanie odbywa się tylko wtedy, gdy występuje ciśnienie w pamięci. Często niezarządzane uchwyty są bardziej ograniczone niż pamięć, więc możesz wyczerpać się z uchwytów przed wystąpieniem GC, powodując błędy.

Ale dla jednej lub dwóch instancji Font nie zaszkodzi ci to zbytnio.

Większym problemem jest to, że niektóre obiekty są wspólne i nie powinno (lub nie mogą) być usuwane przedwcześnie ...

+0

"Często niezarządzane uchwyty są bardziej ograniczone niż pamięć" - Pewnie. Ale czy to prawda, jeśli chodzi o obsługę czcionek GDI +? To część mojego pytania. –

4

Dlaczego nie pozbyć się go, gdy skończysz? To, że mamy zamiatarki uliczne, nie oznacza, że ​​powinniśmy po prostu chodzić po ulicach. Jednak w podanym przykładzie, jeśli czcionka jest potrzebna na czas życia obiektu, pozbądź się czcionki w zbiorze tego obiektu. Jest wiele rzeczy, które upraszczają mój kod, ale to nie usprawiedliwia tych zmian - czasami są rzeczy, które powinieneś zrobić, chociaż to jest ból.

Zawsze dobrze jest posprzątać po sobie. Kiedy już czegoś nie potrzebujesz, pozbądź się go. W ten sposób można uniknąć nieprzyjemnych warunków wyścigu, wyjątków pamięciowych, rysowania usterki i długich, wymagających intensywnego procesora wyrzucania śmieci.

Uważam, że najlepiej jest pozbyć się jednorazowych przedmiotów, jeśli nie są już potrzebne, chyba że istnieje uzasadniony powód, dla którego nie należy (takie jak nie jesteś właścicielem obiektu). Trudniej jest wyśledzić przyczynę problemu niż kodować defensywnie z góry.

W odniesieniu do Font, MSDN says:

Zawsze zadzwonić Dispose przed zwolnieniem ostatnią odwołanie do czcionki.W przeciwnym razie zasoby, których używa, nie zostaną zwolnione, dopóki śmieciarz nie wywoła metody Finalize obiektu czcionki.

Nie mówi, jakie są zasoby, ale fakt, że wyraźnie określają, że powinno to być zrobione, niejawnie zwiększa wagę wywoływania.

+5

Dlaczego nie chcesz go zlikwidować? Otóż ​​OP powiedział dlaczego: ponieważ znacznie uprościłoby to jego kod. –

+2

Kiedy właściwość Czcionka kontrolna (lub właściwość Obrazka lub inna) jest ustawiona na obiekt, który trzymam, w jakich przypadkach kontrolka tworzy kopię obiektu (w takim przypadku powinienem się pozbyć umysłu i pozwolić mu pozbyć się jego) iw jakich przypadkach kontroler spodziewa się dalszego korzystania z przekazanego obiektu? Gdybym miał swoich drutaczy, byłby sposób określenia, czy kontrola powinna przejąć własność przejętego obiektu, ale skoro nie ma, to co należy zrobić? – supercat

+0

@supercat: Dokumentacja powinna wskazywać, jakie są zasady dotyczące własności. Jednak powinieneś przynajmniej założyć, że podczas gdy kontrolka odwołuje się do Czcionki, nie powinieneś jej Zbywać. Spodziewam się jednak, że Kontrola pozbawia czcionkę, gdy się ją pozbywa, ale nie wiem na pewno. –

1

Finalizery są wbudowane w klasy, ponieważ oczyszczanie jest konieczne. Bez względu na to, czy masz dużą lub małą liczbę obiektów do oczyszczenia, dobrą praktyką jest ich czyszczenie.

GC został zbudowany tak, że ma własny pseudo-umysł. Odpowiednio pozbywając się twoich obiektów, pozwalasz GC robić to, do czego zostało stworzone.

Jeśli jednak tworzysz dużą liczbę obiektów fontów i pozbywasz się ich wszystkich, może być korzystne wywołanie GC w odpowiednim generatorze (prawdopodobnie generacja 0) co jakiś czas, aby samodzielnie rozpocząć oczyszczanie GC w zależności od tego, jakie inne obiekty tworzysz dużą liczbę. Twoim celem powinno być utrzymywanie przedmiotów, o których wiesz, że nie używasz zbyt długo, aby uzyskać promocję starszych pokoleń. Dzięki temu zadanie GC jest szczupłe: &.

Po prostu wykorzystaj swoją najlepszą ocenę, a wszystko będzie dobrze. Ale naprawdę pozbywaj się wszelkich przedmiotów za pomocą finalizatora, tak jak zwykła praktyka.

2

Jak ważna jest likwidacja czegokolwiek, co to jest? IMHO, gdy zaczynasz zadawać takie pytania, brzmi to tak, jakbyś miał problem z projektem w swoim kodzie. Powinieneś zawsze pozbywać się rzeczy, których już nie potrzebujesz - to się nazywa odpowiedzialne programowanie.

Możliwe rozwiązania problemu:

  • nie przechodzą wokół obiektów jak Fonts. Zaimplementuj logikę korzystania z czcionek w jednym miejscu (jedna klasa), dodaj czcionkę jako pole tej klasy i zaimplementuj IDisposable dla tej klasy.

  • Wdrożenie czcionki klasę cache - zamiast tworzenia nowych Font obiektów za pomocą operatora new całego kodu, należy użyć tej klasy, aby uzyskać pożądany Font. Klasa może wtedy mieć logikę do ponownego użycia istniejących czcionek, jeśli to możliwe. Lub zachować 10 ostatnich czcionek w pamięci i usunąć pozostałe. Implementacja IDisposable dla pamięci podręcznej, która zostanie wywołana jeden raz w cyklu życia Twojej aplikacji.

+0

W jaki sposób klasa pamięci podręcznej czcionek będzie wiedzieć, kiedy czcionki nie są już używane? Czy musisz "zwrócić" czcionkę do pamięci podręcznej? – Arafangion

+0

Tak, musiałby być sposób, aby powiedzieć, że nie potrzebujesz już czcionki. Zwykle robię to za pomocą jakiejś klasy "Lease", która implementuje 'IDisposable', a w metodzie" Dispose() "kontaktuje się z pamięcią podręczną i mówi, żeby zmniejszyć liczbę odwołań. Ten sam wzór może być stosowany w fabrykach. –

+0

Czy to nie jest powrót do kwadratu? Przynajmniej masz teraz menedżera, który zarządza twoimi prawdopodobnie kosztownymi czcionkami, ale to rodzi pytanie: dlaczego nie powinieneś po prostu zakładać, że konstruktor/fabryka i garbage collector nie mogą wykonać zadania w większości sytuacji? – Arafangion

-2

Mam co najmniej jedną inną uruchomioną aplikację korzystającą z środowiska wykonawczego .NET. Wciąż dostaję OutOfMemoryExceptions. Dobrze byłoby, aby aplikacja zachowywała się, aby inne aplikacje nie zgłaszały wyjątków, gdy nie mają wystarczającej ilości zasobów.

Powiązane problemy