131 messaggi dal 12 febbraio 2001
Avrei bisgono di un chiarimento sul funzionamento del Garbage e Collector e l'implementazione di IDisposable in un oggetto business.
Facendo un esempio pratico ho un oggetto business che rappresenta un messaggio email con allegati.
L'oggetto accetta gli allegati e li salva su disco sul server.
Quando l'oggetto viene salvato rende persistenti le informazioni del messaggio ma non fa niente sugli allegati in quanto li salva su disco subito quando vengono impostati.
Se uso l'oggetto in asp.net ho bisogno di cancellare gli allegati dal disco se il messaggio nonn viene salvato (ad esempio l'utente cambia pagina e non termina la procedura di invio del messaggio dopo aver gia allegato alcuni file)
Ho pensato di implementare il metodo dispose in modo che se l'oggetto è transiente attraverso il Dispose cancello gli allegati dal disco.
La domanda è la seguente. La GC chiama il dispose dell'oggetto se implementa idisposable oppure lo elimina dalla memoria e basta?
Se cosi fosse come faccio per cancellare gli allegati di questi oggetti lasciati transienti e mai salvati?
Ho pensato di utilizzare dei memorystrem, ma in caso di allegati molto grandi ci sarebbe un uso di risorse molto alto. Qualcun o ha dei suggerimenti o soluzioni?

Grazie

Edika
Ciao,

la questione è un pelino più complessa. A mio avviso il tuo cliente potrebbe voler "confezionare" un email da inviare, anche successivamente ad n utenti e quindi voler "persistere" alcuni dati, fra i quali, ad esempio, gli allegati.
Il "salvataggio" su disco degli allegati esula dall'oggetto MailMessage ed il relativo "Dispose" mai invocato in caso di mancato invio.
Ok, in questo caso avrei dovuto "persistere" altri dati tipo l'oggetto della mail, il Body etc. , ma dove se non in db ? o ... vedi tu.
Ergo, se la mail non è stata inviata e non voglio "persistere" i dati non mi resta che intercettare l'evento unload della "pagina" (non voglio "salvare" alcun dato) e verificare se la fatidica mail è stata inviata o meno.
Se non è stata inviata cancello gli allegati, se ci sono, altrimenti, il lavoro di pulizia sarà delegato alla procedura di invio mail.
Si è discusso molto in questo forum un merito a Dispose e GC fai qualche ricerca e troverai tonellate di risposte.

Fabrizio Canevali
176 messaggi dal 04 giugno 2007
Contributi | Blog
Una domanda sorge spontanea: non devi cancellare i file di allegato dal disco del server anche dopo che il messaggio e' stato inviato? Non farlo viola un principio di privacy attesa dall'utente.
Dal punto di vista del ciclo di vita dell'oggetto messaggio, e' la stessa cosa: una volta che il messaggio e' stato inviato o abbandonato, deve essere distrutto insieme a tutte le sue parti.

Passando alla tua domanda: la risposta concisa e' "Si', purche' il tuo oggetto implementi IDisposable correttamente".

Il GC sfrutta per questo il concetto di finalizer (simile ma diverso in alcuni aspetti critici al concetto di un distruttore in C++). In soldoni, un finalizer e' codice che viene chiamato dal GC quando un oggetto nel GC Heap viene raccolto. Il dipose pattern fa si' che il codice del finalizer sia anche esposto ad una chiamata esplicita ad un metodo noto (Dispose()). In pratica, se il dipose pattern e' implementato correttamente, il tuo finalizer non fa altro che chiamare Dispose() sull'oggetto.

Nel tuo caso, chiamare Dispose() sull'oggetto messaggio deve cancellare tutti i file temporanei. Questo puo' avvenire perche' hai chiamato Dispose() esplicitamente sul main thread dell'applicazione o perche' il GC sta eseguendo lo stesso codice attraverso il finalizer sul finalizer thread.
Ovviamente e' molto meglio non contare sul GC per la gestione di risorse diverse dalla memoria.
Nel tuo caso, i file di allegato usano risorse preziose e finite del sistema (file handles). E' importante che siano rilasciate prima possibile (appena l'operazione di invio e' stata completata con successo o abbandonata). Per questo, implementare IDisposable sul tuo oggetto e' la soluzione piu' pulita.

Saluti

--Alessandro
131 messaggi dal 12 febbraio 2001
Ciao Stefano,

in realta il messaggio è un email ma di un sistema di messaggistica interna all'azienda, e gli allegati devono essere conservati.

Se ho capito bene devo implementare IDisposable ed inserire nel Dispose una chiamata al metodo che distrugge gli allegati. Il Dispose dell'oggetto verrà chiamato dal GC al momento in cui verra eliminato.
Ho letto in un articolo su Devx che basta implementare il metodo Finalize per eseguire del codice che si vuole venga eseguito dalla chiamata del GC:

~MailMessage()
{
if(IsNew && HasAllegati)
{
foreach (Allegato allegato in _allegati)
{
DeleteFile(allegato.NomeFileArchivio);
}
}
}

Sarebbe corretto fare cosi nella mia classe senza implementare IDisposable?

Grazie.

Edika
edika ha scritto:
Ciao Stefano,

in realta il messaggio è un email ma di un sistema di messaggistica interna all'azienda, e gli allegati devono essere conservati.

Se ho capito bene devo implementare IDisposable ed inserire nel Dispose una chiamata al metodo che distrugge gli allegati. Il Dispose dell'oggetto verrà chiamato dal GC al momento in cui verra eliminato.
Ho letto in un articolo su Devx che basta implementare il metodo Finalize per eseguire del codice che si vuole venga eseguito dalla chiamata del GC:

~MailMessage()
{
if(IsNew && HasAllegati)
{
foreach (Allegato allegato in _allegati)
{
DeleteFile(allegato.NomeFileArchivio);
}
}
}

Sarebbe corretto fare cosi nella mia classe senza implementare IDisposable?

Grazie.

Edika
Ciao, il GC si occupa di "ripulire" la memoria.
Tramite Dispose non "forzi" il GC anche perchè, fortunatamente, il passaggio del GC non è deterministico e non può essere invocato.
Tramite Dispose non fai altro che "marcare" l'oggetto e "liberare" tutte le sue risorse. Un metodo Dispose deve chiamare il metodo SuppressFinalize (marcatura) per l'oggetto che viene eliminato. Se l'oggetto si trova nella coda di finalizzazione, SuppressFinalize impedisce che venga chiamato il relativo metodo Finalize e il GC si occupa solo di "ripulire" la memoria. Tieni presente che l'esecuzione di un metodo Finalize incide notevolmente sulle prestazioni. Pertanto, se il metodo Dispose ha già eseguito le operazioni di pulitura sull'oggetto, non occorre che il Garbage Collector chiami il relativo metodo Finalize.

Fabrizio Canevali

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.