Newsgroup: it.comp.lang.visual-basic
Titolo: Conessioni multiple - Winsock - Concorrenza

Mettiamo che voglia creare un'applicazione server che possa accettare
un MAX di utenti contemporaneamente.
Mettiamo che posiziono sul form un winsock dal nome SockListen che
metterò in stato di listen.
E mettiamo che posiziono sul form un altro winsock, chiamato Sock(0),
chiuso.
Alla SockListen_ConnectionRequest dovrei caricare un nuovo Sock(n) e
passargli la connectionrequest per fargliela accettare.
Nella ConnectionRequest chiamo una mia funzione GetFreeIndex() che mi
restituisce l'index del primo winsock utilizzabile per accettare la
connessione: perchè inizialmente magari tutto va bene e vengono
utilizzati Sock(0), Sock(1) e Sock(2).
Poi Sock(1) viene chiuso e rimangono Sock(0) e Sock(2).
A quel punto dovrei riutilizzare l'1 per fare Load Sock(1) e
Sock(1).Accept RequestId.
Però nella ConnectionRequest bene o male il codice è:
Private Sub SockListen_ConnectionRequest(ByVal RequestId As Long)
Dim iFree As Long
      iFree = GetFreeIndex()
      If iFree >= 0 Then
        If iFree > 0 Then Load Sock(iFree)
        Sock(iFree).Accept RequestId
        '...
      Else
        '  iFree < 0: raggiunto il limite di connessioni accettabili...
      End If
End Sub
Ma in un mondo in cui vige la legge di Murphy, subito dopo la
GetFreeIndex(), quando ho ottenuto l'indice del primo sock disponibile,
può tranquillamente arrivare una nuova ConnectionRequest(), che chiama
GetFreeIndex(), ottiene lo stesso iFree, utilizza quel Sock(iFree),
finisce, e riprende l'esecuzione della vecchia request, che tenta di
utilizzare iFree, ormai utilizzato da un altro.
Come si può ovviare a una situazione simile? Ho dato un'occhiata al
SimpleWebServer sul sito comune ma la tecnica utilizzata è pressocchè
identica e quindi, IMHO, possiede lo stesso problema...

 ottiene lo stesso iFree
AFAIK in VB, eccezion fatta per alcune chiamate
API, l'esecuzione delle funzioni e degli
eventi e' sincrona e solo tramite DoEvents, si
puo' ritornare alla coda degli eventi e permettere
ad un evento (in coda, per l'appunto) di scattare
(simulando una modalita' asincrona).
Pertanto, se nell'evento ConnectionRequest e nelle
funzioni da esso chiamate, non sono presenti
DoEvents puoi stare tranquillo che non
verra' scatenato l'evento successivo fino alla fine
dell'esecuzione della/e Sub.
Allego un esempio di quanto appena illustrato:
Inserire una ListBox (List1) in un Form (Form1) che abbia
la proprieta' KeyPreview = True.
'------------------------------------------------------------
Option Explicit
'Il numero libero
Private n As Long
'Restituisce il numero libero
Private Function GetN() As Long
    GetN = n
End Function
'Incrementa il numero libero
Private Sub IncreaseN()
    n = n + 1
End Sub
'Quando si preme un tasto qualunque
'esegue una Sub che lo visualizza
'molto lentamente...
Private Sub Form_KeyPress(KeyAscii As Integer)
    Dim iFree As Long
    'Legge il numero libero
    iFree = GetN()
    'Lo mostra... molto lentamente
    Call SlowShow(iFree)
    'Lo incrementa solo alla fine
    Call IncreaseN
End Sub
'Mostra il numero molto lentamente
Private Sub SlowShow(ByVal num As Long)
    Dim t As Single
    'Aggiunge il numero alla ListBox
    Call List1.AddItem(CStr(num))
    List1.ListIndex = List1.ListCount - 1
    Call List1.Refresh
    'E aspetta 2 secondi
    t = Timer
    Do Until Timer - t > 2
        'DoEvents
        'Togliendo il commento dalla riga sopra
        'verra' eseguito il prossimo evento
        'KeyPress nella coda dei messaggi
        'mandando a "signorine" tutto il meccanismo :P
    Loop
End Sub
'------------------------------------------------------------
Il funzionamento e' semplice. Ogni volta che premo un tasto
chiedo il primo numero libero, lo visualizzo molto lentamente
e poi lo incremento.
Premendo piu' tasti in rapida successione, se VB operasse
in maniera asincrona, ogni evento dovrebbe essere scatenato
immediatamente e poiche' l'incremento avviene solo alla fine
si dovrebbe verificare il problema a cui accennavi nel post
originale, ovvero che venga visualizzato sempre lo stesso
numero.
Essendo invece l'esecuzione sincrona, VB si comporta proprio
come vorresti: prima di scatenare l'evento successivo, termina
l'esecuzione del precedente e quindi arriva ad incrementare
il numero... *A MENO CHE* non sia presente un DoEvents in una
qualunque delle funzioni chiamate. In tal caso vengono scatenati
gli eventi successivi in coda sfalsando la visualizzazione.
hth,
Lokar 

 utilizzare iFree, ormai utilizzato da un altro.
Dunque, le chiamate alla SockListen_ConnectionRequest avvengono una alla 
volta, quindi la GetFreeIndex() funziona.
Il problema è che alla disconnessione devi ricordarti di fare l'unload degli 
oggetti caricati.
Ciao
-- 
Free .Net Reporting Tool - 
http://www.neodatatype.net
 

 puÃ² tranquillamente arrivare una nuova ConnectionRequest(),
Può arrivare, ma se non hai inserito un DoEvents, non verrà processata 
fino all'End Sub.
Ciao
Alberto
-- 
A questo punto hanno trovato un muro,
un muro duro, molto molto duro,
che siamo noi.