Newsgroup: it.comp.lang.visual-basic
Titolo: Comunicazione asincrona contemporanea con le due seriali

Problema annoso che mi fa andare in bestia. Ormai non so più
che pesci pigliare, per favore, qualcuno mi aiuti.
Ho creato una classe chiamata Seriale che ha le seguenti proprietà:
Private hFile As Long   ' handle del file aperto
Private strOverlpd As OVERLAPPED ' usata durante la comunicazione
Public Port As Long   ' Porta seriale
Essa è anche "dotata" di alcuni metodi.
Il metodo Connect apre la seriale (CreateFile) e ne ricava un
handle che viene salvato nella proprietà hFile; imposta velocità,
parità e blah blah blah (SetSerialConf o qualcosa di simile,
sfruttando la struttura DCB), imposta i timeout di comunicazione
(SetCommTimeouts o qualcosa di simile). Fatto questo, il metodo
Connect passa il controllo alla procedura di comunicazione
Communicate.
Notare che la porta seriale è stata aperta in modalità OVERLAPPED,
quindi asincrona.
La procedura Communicate, trasmette un byte (WriteFile) ed utilizza
la ReadFile() per leggere un altro byte (ovviamente sulla porta è
connesso un apparato che risponde con un byte alla ricezione di
un byte). Poiché il tutto è asincrono, dopo la ReadFile() genero
un timer (mediante SetTimer) con un identificativo coincidente con
il puntatore all'istanza dell'oggetto Serial (ObjPtr(Me)).
In questo modo, nella routine di callback del timer, posso richiamare
il metodo TimerElapsed dell'istanza corrispondente conoscendone il
puntatore.
Il metodo TimerElapsed controllo, mediante una GetOverlappedResult(),
che l'operazione di lettura sia terminata (notare il membro private
strOverlpd che viene usato sia per la ReadFile sia per la
GetOverlappedResult, così come hFile).
Se la GetOverlappedResult() dice che l'operazione ha avuto termine,
si elabora il byte ricevuto e si ritorna a Communicate (ovviamente
si cancella il timer con KillTimer) altrimenti si esce dalla procedura
senza cancellare il timer. In questo modo, ogni x millisecondi, vado
automaticamente a verificare il termine della procedura di I/O.
Notare che, avendo settato i timeout di comunicazione, anche nel caso
in cui nessun apparato risponda, l'operazione di I/O asincrona termina,
ovviamente dopo il timeout.
Bene, il tutto funziona egregiamente ed io, creando una istanza
dell'oggetto Serial e aprendo la comunicazione, posso osservare i
vari byte che ricevo.
La cosa che non funziona è quando creo due istanze di Serial, ovviamente su
porte diverse (COM1 e COM2) e comunico contemporaneamente con i due
apparati. Quello che succede è che una
porta funziona, cioé scrivo e leggo senza problemi, mentre la seconda porta
non va, nel senso che la GetOverlappedResult() mi dice *sempre*
che l'operazione di lettura *non* ha avuto termine, il che è
praticamente impossibile visto che almeno dovrebbe andare in
timeout.
Appena disconnetto una porta, l'altra riprende a funzionare senza
problemi, appena riconnetto entrambe le porte, una smette di funzionare.
Ho perso veramente la testa, ho inserito dei DoEvents ogni tanto,
chissà il VisualBasic dovesse fare qualcosa nel frattempo, utilizzo sempre
Err.LastDllError e non GetLastError() per essere più efficace.
Niente da fare...
Ovviamente qui il problema è semplificato, quindi non mi chiedete
perché ho deciso di "inventarmi" il meccanismo dei timer. Diciamo che
vorrei far funzionare la cosa in questo modo.
Spero vivamente che qualcuno risponda, scusate per la lunghezza del
post ma non era facile spiegare la situazione, anzi non so neanche se
ci sono riuscito.
Ciao e grazie in anticipo.

Siccome non vedo risposte, mi azzardo io...
Io lavoro con le seriali, però uso il controllo mscomm per la gestione ad 
eventi. In pratica, il form passa un riferimento all'oggetto mscomm ad una 
classe che si cucca i dati. nessun problema a lavorare in parallelo.
MatB
PS: 2 porte => 2 oggetti mscomm...

 classe che si cucca i dati. nessun problema a lavorare in parallelo.
Ovvio, purtroppo quando dicevo che avevo semplificato il problema era
proprio
vero.
Il mio software si collega non solo in connessione diretta via cavo seriale,
ma anche via modem. In quest'ultimo caso ho dovuto usare le librerie TAPI
(Telephony API) per sorpassare il problema dei driver del modem (i comandi
AT
che possono cambiare da modem a modem).
Le TAPI, quando eseguono una chiamata via modem, aprono automaticamente la
seriale su cui il modem è collegato e la aprono automaticamente in modalità
asincrona (overlapped). Quello che posso fare e ripescare l'handle della
connessione ed usare le solite ReadFile() e WriteFile() per ricevere e
trasmettere byte... e sono obbligato ad usare la modalità overlapped.
E' per questo che non posso usare l'oggetto MsComm del Visual Basic, non per
altro. Purtroppo lo so, sarebbe stato molto più semplice ma niente da fare.
Sono costretto ad usare le ReadFile() e WriteFile() (o ReadFileEx() e
WriteFileEx()).
Possibile che nessuno possa aiutarmi? Magari esiste in rete un oggetto tipo
l'MsComm ma scritto da zero con sorgente a disposizione? In altre parole,
non è possibile ottenere il sorgente (ovviamente in Visual Basic) di un
componente simile al MsComm?
Oppure, supponendo di far "aprire" alle TAPI la connessione, è possibile
"agganciare" un oggetto MsComm a questa connessione, conoscendone l'handle?
Grazie in anticipo.