Sincronizza Indice |
Scarica il progetto |
Testo dell'articolo |
Stampa l'articolo |
Difficoltà: 2 / 5 Caricare e scaricare un form dalla memoria potrebbe sembrare un'operazione molto semplice ma nasconde più di un'insidia. È fondamentale ricordarsi che esistono sei operazioni fondamentali legate all'apertura e chiusura di un form; le sei operazioni sono:
Tenendo a mente queste sei operazioni possiamo vedere che esistono tre differenti modalità di istanza di un form:
Queste due differenti argomentazioni danno vita a tantissime combinazioni di funzionamento e malfunzionamento. A tal scopo è stato sviluppato un progetto dimostrativo che a scelta dell'utente carica un form secondario e opzionalmente lo carica, lo scarica e lo dealloca dalla memoria. L'interfaccia si presenta molto semplice ed intuitiva: sono presenti tre pulsanti di nome cmdCaso (con indici da 0 a 3) in grado di generare un riferimento al form da utilizzare nelle tre differenti maniere viste in precedenza. Al di sotto dei pulsanti sono presenti 3 caselle di controllo per la
scelta di tre operazioni possibili: caricamento, scaricamento e deallocazione. Il
form che verrà caricato è straordinariamente semplice: consta
infatti di un unico pulsante in grado di nascondere il form modale aperto.
Questo comporterà quindi il ritorno alla procedura che ne ha richiesto
l'apertura. Il secondo form, di nome Form2, contiene al suo interno una variabile
pubblica di nome intVar che servirà per analizzare il comportamento
del form in funzione delle operazioni richieste e verrà inizializzata
a 0 nell'evento Initialize del form.
Ritorniamo al primo form: la sua vita si compone dell'unico evento Click per tutti e tre i pulsanti, differenziati dal valore del loro Indice. La routine di gestione dell'evento verificherà quale pulsante è stato premuto ed in base a questo aprirà il form nella maniera richiesta: tramite riferimento alla classe base, con dichiarazione di un oggetto e successiva istanza oppure con istanza automatica. Per tutti e tre i casi, comunque saranno eseguite due operazioni: incremento
della variabile membro intVar e visualizzazione in maniera modale del
secondo form. Si raccomanda un test di sperimentazione con tutte le soluzioni possibili,
caricando il form più di una volta e vedere quindi qual'è
la procedura più corretta per il risultato che si vuole ottenere. Il primo di questi utilizza il primo dei tre pulsanti senza selezionare alcuna delle caselle di controllo in basso. Alla prima pressione del pulsante possiamo notare che sono eseguire nell'ordine le seguenti operazioni:
In questo primo caso possiamo analizzare due comportamenti strani: il
primo riguarda la celazione del form mediante il pulsante nascondi. Il
form non viene scaricato dalla memoria ed il numero di forms risulta essere
2. Riapriamo nuovamente il secondo form premendo il primo dei tre pulsanti
e stavolta, invece di nasconderlo semplicemente chiudiamolo mediante il
pulsante di chiusura sulla barra del titolo. Esiste tuttavia una spiegazione logica al problema ed è legata
alla doppia vita dei forms accennata in precedenza. Abbiamo infatti visto
che il riferimento al secondo form è istanziato (evento Initialize)
in occasione della prima apertura dello stesso e seguono quindi normali
caricamenti (evento Load) e scaricamenti (evento Unload).
La doppia vita dei form è quindi determinata da Initialize/Terminate e da Load/Unload. Nonostante sembri normale pensare che lo scaricamento del form dalla memoria ne rimuova tutti i riferimenti non è così. Tale doppia vita è dimostrata anche dal fatto che, se viene incrementato il valore di una variabile quale intVar, il form non viene caricato in memoria, ma soltanto istanziato se non è già avvenuto. Possiamo forzare il caricamento con l'istruzione Load oppure facendo uso di una proprietà o di un metodo intrinseco del form. Il richiamo di un metodo non nativo di un form non forza comunque il caricamento dello stesso, a meno che il metodo non faccia uso di elementi nativi del form. Si può quindi sintetizzare che tutti gli elementi nativi del form fanno parte della vita regolata da Load/Unload, mentre tutti i membri aggiuntivi fanno parte della prima vita del form, regolata da Initialize/Terminate. Per scaricare l'istanza automatica è necessario chiudere il form
che l'ha generata ovvero il primo form. Il secondo caso strano che analizzeremo riguarda anch'esso la doppia vita dei forms ed è in un certo senso l'opposto del caso visto in precedenza. Dopo aver selezionato la casella di controllo Set ... = Nothing, che si occupa di deallocare l'istanza del form in memoria, utilizziamo nuovamente il primo pulsante per richiedere l'istanza automatica del secondo form. In maniera analoga alla precedente possiano notare che scatta il primo evento Initialize e la variabile intVar vale 0; in seguito scatta l'evento Load e la variabile intVar vale 1. Il form è quindi mostrato sullo schermo. Se chiudiamo tale form mediante il pulsante di chiusura sulla barra del titolo possiamo osservare lo scaricamento del form (evento Unload), seguito dalla deallocazione dell'istanza automatica. Il numero di form in memoria è quindi l'inziale 0. Il programma è stato ripristinato allo stato iniziale; se rilanciamo l'apertura del secondo form in maniera analoga gli eventi sono scatenati nella stessa sequenza della precedenza. Proviamo
invece a non chiudere il secondo form dal suo pulsante di chiusura ma
nascondiamolo semplicemente con il pulsante Nascondi. Scatta infatti nuovamente l'evento Initialize nonostante il secondo form
sia ancora in memoria e non siano scattati in precedenza né l'evento
Unload né quello Terminate. Questa è una bruttissima situazione di instabilità: è caricato in memoria almeno un form secondario ma non è possibile avere un riferimento diretto. L'uso dell'istanza automatica con il nome della classe genera infatti un'ulteriore form in memoria. Anche per questa stranezza esiste una spiegazione. Selezionando la casella Set ... = Nothing abbiamo fatto sì che venga deallocata la variabile oggetto ad istanza automatica, ovvero abbiamo distrutto la prima delle due vite del form. Si attende la fine della seconda vita, quella regolata da Load/Unload per distruggere completamente il form e lanciare l'ultimo evento (Terminate) della prima vita. È possibile ristabilizzare la situazione chiudendo il programma oppure facendo doppio click sull'etichetta in fondo al primo form. Funziona anche con il caso precedente ma non era stato accennato per sottolineare l'aspetto dello scaricamento delle istanze disordinato. L'ultimo caso non è per nulla strano ma lo si vuole sottolineare per evitare possibili errori durante lo sviluppo. Dopo aver selezionato la casella di controllo Load, premere un pulsante qualsiasi tra i tre disponibili. Saranno generati in sequenza gli eventi Initialize e Load ma stavolta, a differenza delle situazioni precedenti il valore di intVar sarà 0. La spiegazione è molto semplice. L'istruzione Load forza il caricamento
del form cui segue quindi l'evento Load che nel nostro caso mostrerà
il valore della variabile intVar, prima ancora che le venga assegnato
il nuovo valore. |
Si raccomanda un'analisi del codice per chiarire le sequenze di esecuzioni delle istruzioni e comprendere come evitare situazioni poco piacevoli ristabilizzando quindi l'armonia delle due vite separate degli oggetti Form. Fibia
FBI
|
Torna all'indice delle Stranezze |