Newsgroup: it.comp.lang.visual-basic
Titolo: Unload me non interrompe una sub!

Ecco subito il problema che mi affligge:
-Invio una stringa su un socket.
-Devo aspettare n secondi (diciamo 10)
-Invio un'altra stringa.
Se nei 10 secondi di attesa (il codice e' sotto) la connessione viene
chiusa, l'esecuzione continua nonostante l'unload me! E' come se l'unload
non ci fosse.
Terminal.SendData "Please wait..."
Dim StartTime As Date
StartTime = Time
Do
    DoEvents
    SleepEx 20, -1
Loop Until DateDiff("s", StartTime, Time) > 10
If Terminal.State <> sckConnected Then
    Unload Me
End If
Terminal.SendData "Please retry..."
Mi direte "perche' non usi la gestione errori"? Perche' questo codice e' in
una sub e se anche se rilevo l'errore e tento un altro "unload" neppure
questo viene sentito e l'esecuzione continua fuori dalla sub.
Grazie a chi avra' la pazienza di aiutarmi.
Gio.

 Loop Until DateDiff("s", StartTime, Time) > 10
E' colpa del DoEvents dentro al ciclo, non so perchè, ma il ciclo rimane
sempre come in sospeso e il form che lo ospita non si scarica finchè non si
libera (Mai)
Ho avuto lo stesso identico problema qualche giorno fa', l'ho risolto
sostituendo il ciclo con un Timer.
Bye

*David Ruscelli (Office)* ha scritto:

'Dalla guida (Unload):
'Nota
'Quando un form viene scaricato, viene scaricato solo il componente
visualizzato. Il codice associato al modulo del form rimarrà in memoria.
'E io aggiungo:
'Pure l'avviata (e non conclusa) esecuzione del codice stesso
Dim fermati As Boolean
Private Sub Form_Load()
    fermati = 0
End Sub
Private Sub Command1_Click()
    Do
        Beep
        DoEvents
        If fermati Then Exit Do
    Loop
End Sub
Private Sub Form_Unload(Cancel As Integer)
    fermati = 1
End Sub


Quello che dici, codice di test compreso, corrisponde esattamente con la
verità, però c'era qualcosa che non mi tornava, per quanto riguarda la mia
situazione che giorni fà mi ha portato ad adottare un'altro sistema, tra
l'altro migliore, che lascerò implementato anche se dovessi riuscire a
scoprirela fonte del malessere.
Per fortuna ho imparato a non cancellare mai il codice, ma commentarlo
inserendo la motivazione, quindi mi sono andato a recuperare le istruzioni
che causavano il danno e ho fatto un po' di prove.
Ho creato un progetto di test, per farti vedere una cosa a mio parere
anomala.
Apri un progetto
Caccia in un form un timer e chiamalo timer1
impostalo a 5 secondi
poi copia questo codice (ovviamente ho semplificato tutto per riportare solo
il nocciolo del problema, evitando così di incollare oltre 1000 righe, per
non parlare del fatto che ormai è risaputo, il sorgente scritto è segreto e
non va pubblicato sul NG, qualcuno potrebbe copiare le nostre idee! :-PPP)
Private Declare Function GetTickCount Lib "kernel32" () As Long 'restituisce
i millisecondi di sistema
'---------------------------------------------------------------------------
-----
'Il seguente codice è stato rimosso da Administrator il 08/05/2003 ora 14.55
'Commenti:rimosso perchè sospetto non faccia scaricare la formmain quindi il
programma non si chiude
'
'
'
'
'---------------------------------------------------------------------------
-----
Private Sub Dormi(Millisecondi As Long)
    Dim Tempo As Long
    Timer1.Enabled = False
    Tempo = GetTickCount()
        Do Until (GetTickCount() - Tempo) > Millisecondi
            DoEvents
        Loop
    Timer1.Enabled = True
End Sub
Private Sub Timer1_Timer()
Call Dormi(10000)
End Sub
Lo so che visto così questo codice sembra non abbia senso, ma ripeto che è
solo una semplificazione del problema, in relatà la cosa era inserita in un
contesto ben piu complesso in cui il senso c'era, fidati.
Ora lancia il programma e aspetta 10 secondi(è importante che tu sia
preciso), dopodichè prova a chiudere il form con la X.
Se hai calcolato bene i tempi Vb sta ancora ciclando dentro il loop e
dovrebbe uscire dal programma entro i 5 secondi rimanenti
(5del timer + 10 del ciclo - 10 che hai aspettato)
 Invece io ho atteso fino a 2 minuti ma niente, il form sparisce ma il
programma non si chiude.
Se do una occhiata a che cazzo sta facendo inserendo brutalmente la modalità
debug... vedo una cosa alquanto strana!
NON FA NIENTE! (nessuna riga diventa gialla)
A questo punto ci sono solo due modi per fermare il programma.
1- dalla modalità debug, ripetere l'istruzione unload form1, quindi
simulando pressapoco di nuovo la pressione della X
2- premere il tasto dello stop
entrambe cose che a programma compilato non si possono fare :-P
Ora io mi sono fatto una mezza idea.
Cioè che vb non metta in coda lo scaricamento completo del modulo, se in
quel momento c'è un ciclo in atto..
Però non so....
Mi turba molto il fatto che se togli il timer e associ la funzione di attesa
ad un commandbutton tutto funziona regolarmente, al limite ti tocca
aspettare qualche secondo prima di vedere il programma fermarsi, in quanto
magari c'è ancora il ciclo in atto.
Quindi si può dedurre che timer e ciclo si accavallino, ma non è così, non
si spiegherebbe infatti come è possibile che se dopo 2 minuti metto in debug
non si evidenzia nessuna riga in giallo, quindi il programma non sta
eseguendo nessuna riga di codice, eppure non si è chiuso.
Mi gratto la testa e ti dico che sono perplesso.
Fammi sapere cosa non mi torna, ti prego!
Prima di inviare il messaggio, mentre stavo correggendo gli inevitabili
errori di grammatica, mi è venuto un dubbio....
non è che l'istruzione
Timer1.Enabled = True
in fondo alla routine dormi, mi ricarichi di prepotenza  il form sotto al
culo?
Sai che penso proprio sia così?
Cazzo!
Ci ho zavagliato una mezzagiornata, te lo giuro!
Beh.. fammi sapere che ne pensi.
Un Ruscelli Mooooooooooolto stressato...
:-)

 culo?
Esatto! Come avverrebbe con un riferimento a un qualsiasi controllo del form
(e del form stesso). E qui sotto c'è la dimostrazione (vedi la finestra di
debug alla fine):
Private Declare Function GetTickCount Lib "kernel32" () As Long 'restituisce
i millisecondi di sistema
Private Sub Dormi(Millisecondi As Long)
    Debug.Print Now & "-Dormi"
    Dim Tempo As Long
    Timer1.Enabled = False
    Tempo = GetTickCount()
    Do Until (GetTickCount() - Tempo) > Millisecondi
        DoEvents
    Loop
    If Me.Visible Then
        Timer1.Enabled = True
    Else
        Debug.Print Now & "-Forzo Unload con Timer1 disabilitato"
        Unload Me
    End If
End Sub
Private Sub Form_Activate()
    Debug.Print ""
    Debug.Print Now & "-Activate"
End Sub
Private Sub Form_Load()
    Beep
    Debug.Print Now & "-Load o 'Re-'Load"
End Sub
Private Sub Form_Unload(Cancel As Integer)
    'Timer1.Enabled = False
End Sub
Private Sub Timer1_Timer()
    Debug.Print Now & "-Timer1_Timer"
    Call Dormi(10000)
End Sub