Introduzione
Ho deciso di scrivere un pò di miei utili consigli.....
Tutto solo ed esclusivamente perchè vb6 è morto....o quasi....
Volevo iniziare col dire che vb6 è multithread come si legge su un journal(ma si scrive cosi?eheheh) dell'msdn,che siega passo dopo passo come trasformare il normale svolgimento di un programma vb come nel suo fratellone c++;ovvero tramite il processo dei messaggi,perdendo cosi la grande funzionalità delle chiamate pseudo automatiche di vb.
So già che almeno la metà di voi non ci ha capito una emerita mazza,per farla semplice (per chi conosce il c) esiste un metodo per far lavorare vb6 come c,si ma esce dalla filosofia di vb,diventa tutto maledettamente impossibile e comlicato!infatti casa M ha abbandonato prorio per questo!.
E allora come facciamo?Ehhheheh e qui nasce una mia vecchia sfida...tutto ciò che è c è vb...
E quindi? seguitemi...
Trasformazione
Come fa il linguaggio c a creare un nuovo thread?con l'utilizzo della funzione(api) beginthread(...).
Come facciamo ad utilizzarla in vb?vediamo prima di tutto come è dichiarata in c:
uintptr_t _beginthread(void( *start_address )( void * ),unsigned stack_size,void *arglist);diciamo subito che questa funzione non potremmo chiamarla per motivi che magari spiego un'altra volta,ma grazie a un bug di casa M tutto ciò passerà quasi inosservato,infatti in runtime l'applicazione funzionerà normalmente mentre in debug mode dovremmo intercettare l'errore.
Ok ma cosa ci facciamo con sto codicetto adirittura in c?semplicemente lo convertiamo in vb:
inanzitutto bisogna ricercare in che libreria è,msvcrt.dll,il nome lo conosciamo già,_beginthread,anche se in vb non si possono utilizzare _ basterà semplicemente usare un alias,i parametri sono semplici,il primo è l'indirizzo della funzione da lanciare in multithread,il secondo non ci interessa(almeno per adesso),il terzo sono i parametri da passare.
La parte piu difficile è il decidere se passare i parametri byref o byval,in teoria quando il linguaggio c vuole dei puntatori dovremmo passarci dei byref invece noi useremo i byval.
So che continua ad essere tutto molto vago e complicato ma continuatemi a seguire e vedrete che con due righe lanceremo un thread.
allora ecco come ci si presenta la conversione:
Private Declare Function BeginThread Lib "msvcrt.dll" Alias "_beginthread" (ByVal adrVoid As Long, ByVal StkSize As Long, ByVal Para As Any) As LongPronti partenza VIA!
Tutto qui?Praticamente si,ora farò vedere un suo utilizzo.
Modulo1
'due funzioni multithread di prova,inseriscono un valore incrementale nella rispettiva label.
Public Sub ProvaThread1(ByVal V As Long)
Dim i As Long
For i = 0 To 5000
fMainTest.Label1.Caption = "Multi Thread 1 :" & CStr(i)
fMainTest.Label1.Refresh
Next
End Sub
Public Sub ProvaThread2(ByVal V As Long)
Dim i As Long
For i = 0 To 10000
fMainTest.Label2.Caption = "Multi Thread 2 :" & CStr(i)
fMainTest.Label2.Refresh
Next
End Sub
'Funzione che avvia i thread
Public Sub AvviaThread()
on error resume next
BeginThread AddressOf ProvaThread1, 0, 0&
BeginThread AddressOf ProvaThread1, 0, 0&
on error goto 0
end Sub
fMainTest
inserire 2 label senza cambiarne il nome
inserire un pulsante senza cambiarne il nome
Private Sub Command1_Click()
AvviaThread
End Sub
ecco fatto,COMPILATE e esegute il tutto.
Debug mode
Perchè ho scritto COMPILATE perchè se usate il debug vi da un bel errore nel codice in cui richiama la funzione beginthread,per ovviare a tutto ciò bisogna mettere una gestione degli errore,questa fase serve solo in modalità debug:
Modulo1
'mettiamo la gestione degli errori per farlo funzionare in debug mode.
Public Sub AvviaThread()
on error resume next
BeginThread AddressOf ProvaThread1, 0, 0&
BeginThread AddressOf ProvaThread1, 0, 0&
on error goto 0
end Sub
tutto qui? bhè no,infatti il debug funziona solo con il thread principale piu uno avviato quindi in questo caso salterebbe tutto,come fare? usiamo l'api sleep.
anche se devo fare una precisazione l'api sleep in runtime fa saltare tutto mentre in debug va e viceversa.
runtime + sleep + beginthread = crash
debug + sleep + beginthread =ok
runtime + beginthread = ok
debug + beginthread = crash
il tutto solo ed esclusiavamente quando si usa piu di un thread oltre a quello principale.
come facciamo?usiamo una funzione chiamata debug mode:
Public sub DebugMode() as boolean
Static Contatore as Variant
If IsEmpty(Contatore) Then
Contatore = 1
Debug.Assert DebugMode() or True
Contatore = Contatore - 1
elseIf Contatore = 1 Then
Contatore = 0
end if
DebugMode=Contatore
end sub
ecco ora scrivendo:
If DebugMode then sleep(800)
...
oppure
if DebugMode then on error resume next
...
cosi potrete gestire le due varianti,ide e compilato.
Conclusioni
Casa M dichiara che nella sucessiva versione elementi tipo objptr,il bug qui descritto potranno non esserci piu quindi ne sconsiglia l'utilizzo,francamente poteva sconsigliare l'utilizzo di tutto vb6 dato che non c'è rimasto piu niente

Spero vi sia di aiuto,dimenticavo se volete gestire delle pause dentro un thread dovete usare la beginthreadex.Adirittura con codesta funzione potete avviare un trhead in stato di pausa.
Le applicazioni (soprattutto compilate) saranno molto stabili ma per un programmatore poco esperto potrebbero esserci chiusure inaspettate del programma,quindi salvate sesso,e consiglio quando si è in dubug mode di usare uno sleep di almeno 800 se si utilizza piu di un thread oltre al principale.
un saluto