2009-04-15 15 views
16

Sono consapevole del fatto che la procedura migliore è chiamare Dispose su qualsiasi oggetto che implementa IDisposable, in particolare oggetti che racchiudono risorse limitate come handle di file, socket, handle GDI, ecc.Quanto è importante disporre un font, davvero?

Ma sto correndo in un caso dove ho un oggetto che ha un font, e dovrei scandagliare IDisposable attraverso diversi strati di oggetti, e rivedere molti usi, per essere sicuro di avere sempre il carattere disposto. E mi chiedo se ne valga la pena.

Sarebbe una cosa se Carattere ha avvolto un HFONT, perché le risorse GDI sono globali del sistema. Ma il carattere non include un handle GDI; è GDI +, che è un sistema completamente separato e, per quanto ho capito, è process-local, non system-global come GDI. E a differenza di Image, Font non tiene mai le risorse del filesystem (che io conosca, comunque).

Quindi la mia domanda è: qual è il costo reale di consentire a un font di raccogliere i rifiuti?

So che vorrei ottenere un piccolo successo per il finalizzatore, ma se il numero di caratteri "persi" è piccolo (diciamo una mezza dozzina), quello colpito onestamente non sarebbe evidente. A parte il finalizzatore, questo non sembra molto diverso dall'assegnare un array di medie dimensioni e lasciare che il GC lo pulisca: è solo memoria.

Ci sono dei costi di cui non sono a conoscenza nel consentire a un font di ricevere GCed?

risposta

5

Risposta semplice: se solo alcune, allora no. Se è molto, allora sì. Se la tua applicazione sta già stressando il garbage collector, allora si. Userei il perfmon per visualizzare il numero di oggetti che siedono in giro e il numero che viene promosso alle generazioni più elevate, e poi decidere.

4

Il problema è che la garbage collection si verifica solo quando è presente una pressione di memoria. Spesso, gli handle non gestiti sono più limitati della memoria, quindi puoi esaurire gli handle prima che si verifichi GC, causando errori.

Ma per una o due istanze Font, non ti farà troppo male.

Un problema più grande è che alcuni degli oggetti sono condivisi e non deve (o non può) essere smaltiti prematuramente ...

+0

"Spesso le maniglie non gestite sono più limitate della memoria" - Sicuro. Ma è vero per i manipoli di caratteri GDI + in particolare? Questa è parte della mia domanda. –

4

Perché non lo smaltiresti una volta che hai finito? Solo perché abbiamo spazzini non significa che dovremmo andare in giro a sporcare le strade. Tuttavia, nell'esempio fornito, se il font è necessario per la durata dell'oggetto, smaltire il carattere in tale oggetto. Ci sono molte cose che potrebbero semplificare anche il mio codice, ma questo non giustifica quei cambiamenti - a volte ci sono cose che dovresti fare, anche se è un dolore.

È sempre una buona idea riordinare dopo te stesso. Quando non hai più bisogno di qualcosa, smaltiscila. In questo modo puoi evitare brutte condizioni di gara, eccezioni di memoria, problemi di disegno e lunghe raccolte di dati inutili dal processore.

Trovo che sia la soluzione migliore per smaltire gli oggetti usa e getta se non sono più necessari a meno che non ci sia un motivo giustificabile per non farlo (come se non si possieda l'oggetto). È più difficile rintracciare la causa principale di un problema piuttosto che codificarlo in modo difensivo.

Per quanto riguarda i caratteri, MSDN says:

chiamare sempre Dispose prima di rilasciare il vostro ultimo riferimento al tipo di carattere.Altrimenti, le risorse che sta utilizzando non verranno liberate fino a quando il garbage collector non chiama il metodo Finalize dell'oggetto Font.

Non dice quali sono le risorse ma il fatto che affermino esplicitamente che ciò dovrebbe essere fatto aggiunge implicitamente importanza alla chiamata di Dispose.

+5

Perché non lo smaltiresti? Bene, l'OP ha detto perché: perché avrebbe enormemente semplificato il suo codice. –

+2

Quando la proprietà Font di un controllo (o la proprietà Picture, o qualsiasi altra cosa) è impostata su un oggetto che tengo, in quali casi il controllo crea una copia dell'oggetto (nel qual caso dovrei disporre di mente, e lasciare che si disfi) e in quali casi il controllo si aspetta di continuare a utilizzare l'oggetto trasmesso? Se avessi i miei druthers, ci sarebbe un modo per specificare se un controllo dovrebbe assumere la proprietà di un oggetto passato, ma poiché non c'è, cosa si dovrebbe fare? – supercat

+0

@supercat: la documentazione dovrebbe indicare quali sono le regole in materia di proprietà. Tuttavia, dovresti almeno assumere che mentre il controllo fa riferimento al Font, non dovresti Smaltirlo. Mi aspetto, tuttavia, che il controllo disponga il font quando viene eliminato, ma non lo so per certo. –

1

I finalizzatori sono incorporati nelle classi in modo specifico perché è necessaria la pulizia. Indipendentemente dal fatto che si abbia una grande o piccola quantità di oggetti da pulire, è buona norma pulirli.

Il GC è stato costruito per avere una pseudo-mente propria. Eliminando correttamente i tuoi oggetti, stai permettendo al GC di fare ciò che è stato fatto per fare.

Tuttavia, se si sta creando un gran numero di oggetti font e si eliminano tutti, potrebbe essere utile chiamare il GC sulla generazione appropriata (probabilmente generazione 0) ogni tanto per avviare una pulizia GC da soli a seconda del tipo di altri oggetti che instanziate in grande numero. Il tuo obiettivo dovrebbe essere quello di mantenere gli oggetti che sai non stai usando da molto tempo per essere promosso alle generazioni più anziane. Ciò mantiene il significato del lavoro del GC &.

Usa il tuo giudizio e starai bene. Ma, in effetti, elimina qualsiasi oggetto con un finalizzatore come tua normale pratica.

2

Quanto è importante smaltire lo di qualsiasi valore, davvero? IMHO quando inizi a fare questo tipo di domande, sembra che tu abbia un problema di progettazione nel tuo codice. Dovresti sempre disporre di cose che non ti servono più - si chiama programmazione responsabile.

possibili soluzioni al problema:

  • non passano attorno agli oggetti come Fonts. Implementare la logica di utilizzo dei caratteri in un unico punto (una classe), aggiungere il carattere come campo di quella classe e implementare IDisposable per quella classe.

  • implementare un carattere di classe della cache - invece di creare nuovi Font oggetti utilizzando l'operatore new su tutto il codice, utilizzare questa classe per ottenere il Font desiderato. La classe può quindi avere la logica per riutilizzare i font esistenti, se possibile. O per conservare gli ultimi 10 caratteri in memoria e smaltire gli altri. Implementare IDisposable per la cache, che verrà chiamato una volta nel ciclo di vita della tua app.

+0

Come saprebbe la classe Font Cache quando i font non vengono più utilizzati? Dovresti "restituire" il carattere alla cache? – Arafangion

+0

Sì, ci dovrebbe essere un modo per dire che non hai più bisogno del font. Solitamente lo faccio usando una sorta di classe 'Lease' che implementa' IDisposable', e nel metodo 'Dispose()' contatta la cache e dice di diminuire il conteggio dei riferimenti. Lo stesso modello può essere utilizzato per le fabbriche. –

+0

Non è quello di nuovo al punto di partenza, quindi? Almeno, però, ora avete un manager che gestisce i vostri font presumibilmente costosi, ma questo non fa sorgere la domanda: perché non dovreste semplicemente presumere che il costruttore/fabbrica e il garbage collector non possano svolgere il compito nella maggioranza di situazioni? – Arafangion

-2

Ho almeno un'altra app in esecuzione che utilizza il runtime .NET. Continuo a ricevere OutOfMemoryExceptions. Sarebbe bello fare in modo che l'applicazione si comporti in modo che altre app non generino eccezioni quando non sono in grado di ottenere risorse sufficienti.

Problemi correlati