Newsgroup: it.comp.lang.visual-basic
Titolo: [.Net] Chiarimenti sull'uso di Dispose

Ciao a tutti.
Pensavo di fare una grande mossa invece ho fatto un casino...
Ho un form (chiamiamolo Form1) da cui apro un altro form (Form2) con il
metodo ShowDialog.
Form2 contiene un po' di controllil bindati ed un mio controllo per lo
scorrimento e la gestione di questi controlli (utilizzo il
bindingmanagerbase).
Quando chiudo Form2 avevo messo una chiamata a Form2.Dispose.
Riaprendo Form2 mi succedono strani errori sui metodi AddNew oppure
CancelUpdate del BindingManagerBase (che invece durante la prima apertura
funzionavano perfettamente).
Se invece di mettere Form2.Dispose metto semplicemente Form2 = Nothing,
quando riapro Form2 gli errori spariscono e tutto funziona correttamente.
Qualcuno mi sa spiegare perchè?
Riporto uno stralcio (semplificato) del codice:
Private Sub ApriElemento()
    Dim oForm2 As Form2
    oForm2 = New Form2()
    ' Imposto un po' di proprietà
    [...]
    oForm2.ShowDialog()
    'Se lascio questa riga le entrate successive funzionano
    oFrmModificaTab = Nothing
    'Se lascio questa riga le entrate successive provocano errori
    oFrmModificaTab.Dispose()
End Sub
Ciao e grazie
Skysurfer

 End Sub
ehm.... oForm2 e oFrmModificaTab sono la stessa cosa?
Salutoni
Sergio

 ha scritto nel messaggio
news:basr76$377h6$1...@ID-173193.news.dfncis.de...

Ah si! Scusa...
Accidenti, lo sapevo che a cambiare i nomi dei form prima di postare avrei
fatto casini invece di semplificare!
Ciao
Skysurfer

Ehm, scusate, che differenza c'è tra Show() e ShowDialog() ????


ShowDialog visualizza un form modale. E' come in VB6 quando fai
form.Show(vbModal)
Ciao
Skysurfer


 Mmmm dunque l'argomento è delicato! Quindi ti faccio una domanda, ma tu hai
implementato l'interfaccia IDisposable e il metodo Dispose?
Data la complessita ( forse della domanda ) mi posti la parte di definizione
della tua classe form ( se ti va ! )?
Ciao
--------------------------------
Inviato via 
http://usenet.libero.it

 tu hai implementato l'interfaccia IDisposable e il metodo Dispose?
Curiosità sicuramente interessante, anche se credo che skysurfer utilizzi il
metodo dispose della classe form e non ne abbia ridefinito uno
personalizzato.
Leggendo meglio il codice, e stabilito che in luogo di quel oFrmModificaTab
andrebbe letto oForm2, la mia perplessità è un'altra: tutte le volte che io
eseguo il codice di questa sub, creo una nuova istanza della classe form2.
Perchè l'istanza precedente, per essere precisi il fatto che l'istanza
prededente sia stata "terminata" o meno, influisce sulla nuova? Non è che
c'è di mezzo l'utilizzo di qualche oggetto globale, condiviso da tutte le
istanze?
Salutoni
Sergio

 istanze?
Esatto, io non ho ridefinito il metodo Dispose, ma utilizzo quello scritto
automaticamente da VB.
Non ho oggetti globali, ma una cosa che forse potrebbe avere impostanza è
che in realtè Form2 eredita da un altro Form di base. Ed è in questo Form di
base che ho messo il controllo che poi provoca l'errore
(myDataControl_Net1). Ma forse a questo punto le cose diventano un po'
troppo incasinate...
Questo comunque è il codice del mio form base:
Public Class frmModTabBase
    'Form di base per la modifica degli elementi delle tabelle.
    'Implementa le funzionalità di base comune a tutti i form di modifica
tabelle.
    Inherits System.Windows.Forms.Form
    'Variabili private
    'Datatable da gestire
    Friend m_DataTable As DataTable
    'Oggetto DAL per la gestione degli aggiornamenti del database
    Dim m_DAL As myDAL
    #Region " Codice generato da Progettazione Windows Form "
    Public Sub New()
        MyBase.New()
        'Chiamata richiesta da Progettazione Windows Form.
        InitializeComponent()
        'Aggiungere le eventuali istruzioni di inizializzazione dopo la
chiamata a InitializeComponent()
    End Sub
    'Form esegue l'override del metodo Dispose per pulire l'elenco dei
componenti.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub
    Friend WithEvents myDataControl_Net1 As myDataControl_Net
[...]
End Class
Grazie e ciao
Skysurfer


 Ok, torniamo la problema iniziale, allora quando tu "setti" a nothing una
riferimento, lo stai rilasciando logicamente, questo fa si che quando il GC
lo "riterrà opportuno" verificherà che il tuo oggetto non è più referenziato
e provvederà al rilascio della memoria da esso allocata.
Ora il problema è che "non è dato sapere" ( a meno di forzarlo ) quando il
GC deciderà di "passare in rassegna" il pool di memoria llocata per
rilasciare quelle non più utilizzata.
Detto questo, quando tu "setti" a Nothing il riferimento alla tua form, non
è detto che essa venga distrutta subito, quindi può essere che dopo un pò tu
la riapri e quella esiste ancora!
In effetti la regola sarebbe PRIMA richiamare il Dispose() per rilasciare le
varie risorse, POI "settare" il riferimento a Nothing.
L'argomento non è finito qui perchè in tutta questa "giostra" entra in gioco
anche l'evento "Finalize" che viene invocato dal GC prima di rilasciare la
memoria di un oggetto.
P.S.
 1) Potrei aver detto qualche ca33ata, ma che vuoi sto inziando ora con .NET
 2)C'è solo una cosa che mi sfugge, coma fai a chiamare il Dispose() sulla
form senza parametri...sento che mi sta sfuggendo qualcosa.


  con .NET
detto anche disclaimer ;-) non ti preoccupare, una cazzata in piů o in meno
non sposta i termini del discorso
Salutoni
Sergio

 ha scritto nel messaggio
news:213Z156Z54Z138Y...@usenet.libero.it...

Già... tutta questa teoria era quello che avevo capito io leggendo un po' in
giro. Ed è proprio per questo che non volevo "accontentarmi" di settare a
Nothing il mio oForm2, ma volevo chiamare il Dispose.
Adesso che me lo fai notare non so come faccio a chiamare Dispose() senza
parametri. Nel form2 la sub Dispose è definita così:
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
Ma quando scrivo oForm2.Dispose me lo accetta, senza segnalare l'errore per
la mancanza del parametro e l'intellisense non mi fa nemmeno vedere che devo
scrivere il parametro.
Boh... mi sa che mi sono incasinato troppo.
Ciao e grazie.
Skysurfer


 
  Ci ho riflettuto, porbabilmente ( ma sto approfondendo ) tu richiami il
metodo Dispose() ereditato della classe base e non quello ridefinito nella
tua applicazione.
Probabilmente è proprio questo il problema, prova a chiamare il Dispose(
true ) e poi setta a nothing e vedi che succede.



  Vero, ma se osservi bene lui chiama la Dispose() senza parametri che è
probabilmente ereditata dalla classe base e non quella ridefinita nel classe
che eredita.



Non posso chiamare Dispose(True) perchè mi segnala errore nel numero di
parametri.
In effetti se crei un sempice form (frmProva) e poi istanzi una variabile di
tipo frmProva, vedrai che quando scrivi frmProva.Dispose non ti permette di
specificare parametri, anche se nel codice di frmProva la sub dispose è
stata definita con un parametro.
Ciao.
Skysurfer

 Ciao.
 Mmmm hai ragione, è un metodo protetto! E allora credo sia corretto chiamare
Dispose(), ma per l'errore mi sto ancora documentando.
