Connessione al database con Visual Basic NET? Lo trovi su Opentraining.it Visual Basic Italia
PRINCIPALE > COMUNICAZIONE SERIALE: SESTA PARTE

Eseguire una ricerca veloce nell' archivio delle risorse di Visual Basic Italia®: 

Preso dall'archivio...

Premere il pulsante sotto per accedere direttamente ad un articolo o ad un esempio preso in modo casuale dall'archivio.



Ultimo e-book pubblicato:

"INTRODUZIONE AI CSS"

Lo scopo del CSS language è quello di controllare lo stile dei vari elementi che concorrono a formare un
documento HTML.
Si può operare in tre modi collegamento ad un foglio di stile esterno;definizione degli stili all'inizio
del documento utilizzo della proprietà style all'interno di un Tag HTML (embedded style). Questo e-book introduttivo
servirà per apprendere tali nozioni fondametali dei fogli di stile.

Prezzo: € 0.0.
Presentazione:
REAL SOFTWARE RILASCIA LA VERSIONE 5.0 di REALbasic per Windows






Gorizia, 5 maggio 2003 - Active, distributore in esclusiva di REALSoftware, Austin, Tx, annuncia la disponibilità di REALbasic 5.0 per Windows, uno strumento per lo sviluppo semplice da usare che permette agli utenti Windows di tutti i livelli di creare applicazioni personalizzate e di compilarle sia per la piattaforma Windows che per quella Macintosh.
[>>]

http://www.active-software.com

 

Contatti. Utilizzare l'email generica per domande relative al sito:
Porre domande relative al sito
oppure scrivere ad un responsabile di area.
Responsabile del sito: >Andrea Martelli
Responsabile area "Corso di VB":
> Giorgio Abraini

Comunicazione seriale (sesta parte)

Questa lezione, consultata da 11150 utenti, è stata giudicata di ottimi contenuti , con un'esposizione perfettamente comprensibile e con un livello di approfondimento ottimo da 103 votanti.


Il flusso delle funzioni verso la porta seriale

Prima di introdurre la seconda funzione di accesso alla porta seriale è necessario aver una visione generale di come avviene il flusso delle funzioni che tentano di operare sulla porta stessa.
S'immagini infatti di avere due operazioni distinte ma contemporanee, una di accesso alla porta in lettura e l'altra in scrittura. Quale delle due verrà eseguita per prima?
E' possibile poi costruire un'applicazione che permetta a più funzioni di operare contemporaneamente?
La risposta ai quesiti sta nel fatto che processi di comunicazione distinti (ad esempio il procedimento di lettura e quello di scrittura) possono essere nonoverlapped (ossia non accavallati) nel senso che un'operazione viene effettuata solamente quando l'altra è terminata.
Questo sistema risulta particolarmente utile nelle applicazioni con più processi (ad esempio quando le operazioni sulla porta seriale risultano essere molto lunghe oppure quando le funzioni che vi accedono sono diverse).
Rappresenta un compito dell'applicazione gestire la sequenza di funzioni che accedono alla porta in modalità overlapped. Ad esempio se si richiamano le funzioni di scrittura e di lettura, l'applicazione darà l'accesso soltanto alla prima, bloccando la seconda finché l'operazione precedente non ha terminato il proprio lavoro.
Questo flusso si rivela molto ordinato e di conseguenza permette un utilizzo della memoria molto razionale. Proprio per questi motivi è il sistema generalmente più diffuso.
La figura sottostante rappresenta in maniera astratta l'avvicinamento contemporaneo di più funzioni verso una porta seriale.


Processi overlapped

L' accavallamento delle funzioni nel percorso verso la porta seriale ossia la modalità overlapped è un procedimento non tanto diretto quanto il precedente ma permette una maggiore flessibilità ed efficienza.
Quando la porta seriale è aperta alla comunicazione infatti più funzioni possono eseguire allo stesso momento operazioni di lettura e scrittura, anche se altri processi risultano ancora pendenti.

Ciononostante è necessario non abusare della possibilità di mantenere attivi più processi in quanto l'efficienza ne potrebbe risentire a causa dell'ammontare di memoria richiesta che si accumula in base al numero di funzioni attive.
A questo sguardo generale sui processi si può aggiungere che la modalità overlapped di accesso ad una porta seriale si compone di due parti distinte:

1. la creazione dell'operazione
2. il controllo del suo effettivo successo

La creazione di un processo overlapped implica innanzitutto la creazione di un evento di sincronizzazione tramite la funzione CreateEvent. Il controllo invece avviene semplicemente con l'arrivo del valore di ritorno della funzione. Se questo è differente da -1 allora si può passare alla gestione dei dati ricevuti dalla funzione, in caso contrario utilizzando la funzione GetLastError si otterrà un tipo di errore indicativo del problema incontrato (nel caso di comunicazione overlapped si riceverà presumibilmente un errore del tipo ERROR_IO_PENDING che indica che la funzione ha incontrato un problema durante la sua esecuzione).

Prima di cominciare, quale dei due metodi si può ritenere il migliore? La risposta dipende naturalmente dal numero delle funzioni che s'incontrano al cosiddetto "collo di bottiglia", ossia a quello che nella prima figura è stato indicato come "blocco delle funzioni gestito dall'applicazione": più funzioni attendono e solamente una passa. Non soltanto un processo overlapped richiede più lavoro alla memoria, ma è soggetto anche a un maggior numero di errori: se un'operazione nonoverlapped infatti fallisce, la funzione ritorna l'errore (presumibilmente il valore -1). Se è invece un'operazione overlapped a fallire, le possibili cause di errore possono essere molteplici: errore nella creazione dell'operazione, errore nel processo ancora pendente, time-out dell'operazione, time-out nel controllo del successo dell'operazione.
Una volta scelto il tipo di flusso di funzioni che si desidera utilizzare, è necessario svilupparlo.
Mentre per un processo nonoverlapped basterà utilizzare il codice dell'esempio riportato nell'articolo precedente, per effettuare un processo overlapped è necessario fare alcune modifiche.
Siccome però nella continuazione di questa serie di articoli si utilizzerà unicamente una comunicazione nonoverlapped, dell'altra si analizzeranno solamente i tratti principali e la struttura di fondo.
Una nota da sottolineare prima di cominciare è che i processi accavallati o non (overlapped e nonoverlapped) sono ben distinti dal concetto di comunicazione sincrona e asincrona. Mentre questo indica infatti il processo di trasferimento dei dati, quello rappresenta come può essere gestito il traffico di funzioni verso la porta seriale.

Il punto da cui cominciare è la modifica della funzione CreateFile, utilizzata come già visto, per accedere alla porta seriale. Era stato usato in precedenza la seguente linea di codice:

nPorta = CreateFile("COM1", GENERIC_READ Or GENERIC_WRITE, 0, 0&, _
OPEN_EXISTING, 0, 0)

indicando quindi come penultimo parametro (dwFlagsAndAttributes) il valore 0. Questo implica la creazione di un procedimento nonoverlapped: la funzione attenderà il termine di eventuali processi pendenti.
Se si vuole invece impostare un processo overlapped bisognerà invece fare uso della costante FILE_FLAG_OVERLAPPED facente riferimento alla struttura OVERLAPPED che tiene traccia delle operazioni simultanee:

Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type

A questo punto dovremo creare un oggetto-evento indicativo per ogni funzione di accesso alla porta, dandogli uno stato iniziale. I possibili stati di questo oggetto sono due: signaled e non-signaled. Quando l'oggetto che si andrà ad associare a ciascuna funzione è nello stato signaled significa che l'operazione è terminata.
A tale scopo si farà uso della funzione CreateEvent:

CreateEvent Security, False, True, "Evento-lettura"

Dove l'ultimo parametro, ossia "evento-lettura" è un nome qualsiasi che si può scegliere per identificare il tipo di operazione a cui è associato l'evento stesso. Ricordarsi di inserire nel codice la struttura SECURITY_ATTRIBUTES a cui punta il primo parametro della CreateEvent
La funzione ReadFile invece dovrà essere modificata in questo modo:

vRitorno = ReadFile(nPorta, Carattere(1), Lunghezza_Buffer, Dati_Ricevuti, _ overlaps(0))

dove overlaps(0) indica un'array di strutture OVERLAPPED ciascuna contenente le informazioni su una diversa operazione pendente. Ad esempio la prima struttura di overlaps() può essere utilizzata per le operazioni di lettura in background, la seconda per quelle di scrittura e la terza per monitorare lo stato della porta alla ricerca di eventuali errori.
Associare una struttura ad una funzione è semplice: si utilizza nuovamente l'evento creato appositamente. Ogni struttura OVERLAPPED fa infatti riferimento ad un oggetto Event che rappresenta il collegamento struttura - funzione.
E' quindi possibile utilizzare la funzione WaitForSingleObject per determinare in ogni momento lo stato dell'oggetto-evento:

Declare Function WaitForSingleObject Lib "kernel32" Alias "WaitForSingleObject" _ (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

Dove hHandle definisce l'oggetto del quale determinare lo stato (quindi nello specifico l'oggetto evento della struttura OVERLAPPD) e dwMillisecons è il tempo massimo di attesa. Se l'attesa supera questo tempo massimo verrà ritornato il valore WAIT_TIMEOUT, se una qualsiasi operazione sulla porta è terminata WAIT_OBJECT_0, in caso contrario WAIT_ABANDONED.

Un esempio di processi overlapped può essere rappresentato dal codice che segue. Prendiamo in esame solamente una funzione. Su una casella di testo verrà visualizzato se la funzione sia è esecuzione oppure se c'è un'altra funzione in corso. Chiaramente avendo preso in considerazione una sola funzione il risultato sarà obbligatoriamente il primo, ma allargando il codice al caso di più funzioni (utilizzando come già visto una matrice di strutture, una per ogni funzione), si otterrà il risultato desiderato. Sono state omesse le dichiarazioni delle funzioni già analizzate nel corso degli articoli precedenti:

Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type

Private Type OVERLAPPED
Internal As Long
InternalHigh As Long
offset As Long
OffsetHigh As Long
hEvent As Long
End Type

Private Sub Form_Load()
Dim nPorta As Long
nPorta = CreateFile("COM2", GENERIC_READ Or GENERIC_WRITE, _
FILE_FLAG_OVERLAPPED, 0&, OPEN_EXISTING, 0, 0)
Dim Security As SECURITY_ATTRIBUTES
CreateEvent Security, False, True, "Evento"
End Sub

Private Sub Timer1_Timer()
Const Lunghezza_Buffer = 10
Dim Dati_Ricevuti As Long
Dim Carattere(1 To Lunghezza_Buffer) As Byte
vritorno = ReadFile(nPorta, Carattere(1), Lunghezza_Buffer, Dati_Ricevuti, _ Evento)
Select Case vritorno
Case 0
Text1.Text = "La funzione è in esecuzione"
Case Else 'presumibilimente utilizzando la funzione GetLastError si otterrà il 'valore
'ERROR_IO_PENDING, ma non è fondamentale conoscere il tipo di problema
'incontrato dalla funzione

Text1.Text = "Errore nell'esecuzione"
End Select
End Sub