Newsgroup: it.comp.lang.visual-basic
Titolo: Timer abilitato ma non scatta nessun evento

Salve, mi sfugge qualche cosa che non capisco...
Ho una routine ed un timer;
la routine apre la porta com dove c'e' il modem, fa la chiamata e manda
tutti i dati.
Il timer mi serve per avere delle pause tra una operazione ed un'altra,
valuta le risposte della com (mscomm1.input) e svuota il buffer.
Se una risposta della com e' "No carrier", il timer ripassa il controllo
alla routine chiamante la quale ripete tutte le operazioni.
Il primo ciclo funziona egreggiamente, il secondo no.
Nello specifico ho:
    Do While timerPause.Enabled = True
        DoEvents
    Loop
Il che blocca l'esecuzione di altri comandi finche' il timer e' abilitato.
Il problema e' che il timer non esegue nessuna istruzione.
Dim Posizione As Integer
    lblStatus.Caption = "TimerPause Attivato"
ed anche se metto un punto di interruzione sulla lblStatus, il programma non
si bolcca.
Ho provato, tramite Finestr Immediata a verificare che :
TimerPause.Enabled = True
TimerPause.Interval = 3000
Per quale motivo questo Timer, nel secondo cilco, non scatta?
Non vi posto il codice delle due routine, sarebbe lunga per voi capirci
qualche cosa (sto alle prime armi e si vede) e non voglio abusare troppo
della vostra pazienza
Ciao... Maurizio

 wrote:
[cut]
Hai verificato col Trova di VB che non ti sia scappato un
TimerPause.Enabled = False di troppo nel codice?
Ciao!

 abusare troppo della vostra pazienza
Quando premi la X per chiudere la form, il programma si arresta o non
risponde?
Se non si arresta, hai un loop da qualche parte senza doevents.
Se posti il codice posso dirti qualcosa...
Ciao
Alberto

 abusare troppo della vostra pazienza
Forse avresti fatto meglio...
Comunque, ma cerca eventuali timerPause (se questo è il nome del timer)
.Enabled e vedrai che trovi il quibus. Se non lo trovi, vedi la sua
proprietà Enabled da progetto.


Ciao ciao e buon lavoro

 Se posti il codice posso dirti qualcosa...
...
L'hai voluta tu :-)))
Ecco le due routine incriminate
Private Sub SendAMessage()
    Dim I  As Byte
    Ripeti = False
    Contatore = 0
    If FF2 = 0 Then FF2 = FreeFile
    On Error Resume Next
    Open (App.Path & "\SCsms.log") For Output As #FF2
    Print #FF2, Now
    On Error GoTo 0
    NelBuffer = ""
    MSComm1.CommPort = Porta
    MSComm1.Settings = "9600,N,8,1"
    MSComm1.InputLen = 0
    Print #FF2, "Apro com " & Porta
    lblStatus.Caption = "Apro porta"
    MSComm1.PortOpen = True
    DoEvents
    lblCom.Caption = MSComm1.Input
    lblStatus.Caption = "Comando ATEI1"
    Print #FF2, "Mando Comando ATEI1"
    MSComm1.Output = "ATEI1" & vbCr
    DoEvents
    chiamante = "SendAMessage"
    timerPause.Interval = 3000
    timerPause.Enabled = True
    Do While timerPause.Enabled = True
        DoEvents
    Loop
    NelBuffer = ""
    'lblCom.Caption = MSComm1.Input
    lblStatus.Caption = "Comando ATX3"
    MSComm1.Output = "ATX3" & vbCr
    DoEvents
    chiamante = "SendAMessage"
    timerPause.Interval = 3000
    timerPause.Enabled = True
    Do While timerPause.Enabled = True
        DoEvents
    Loop
    If Prefisso = "X" Or Prefisso = "x" Then Prefisso = ""
    MSComm1.Output = "ATDT" & Prefisso & "3359609600" & vbCr
    lblStatus.Caption = "Chiamo Centro servizi"
    timerPause.Interval = 15000
    timerPause.Enabled = True
    Do While timerPause.Enabled = True
        DoEvents
    Loop
    If Ripeti = True Then
        timerPause.Enabled = True
        Exit Sub
    End If
    For I = 1 To 3
        NelBuffer = ""
        lblStatus.Caption = "Mando ritorno a capo n. " & I
        MSComm1.Output = vbCr
        chiamante = "CR"
        timerPause.Interval = 1000
        timerPause.Enabled = True
        Do While timerPause.Enabled = True
            DoEvents
        Loop
    Next I
    NelBuffer = ""
    lblStatus.Caption = "Numero destinatario"
    MSComm1.Output = NumeroDestinatario & vbCr
    timerPause.Enabled = True
    Do While timerPause.Enabled = True
        DoEvents
    Loop
    For I = 1 To 4
    NelBuffer = ""
        lblStatus.Caption = "Mando ritorno a capo n. " & I
        MSComm1.Output = vbCr
        chiamante = "CR"
        timerPause.Interval = 1000
        timerPause.Enabled = True
        Do While timerPause.Enabled = True
            DoEvents
        Loop
    Next I
    NelBuffer = ""
    lblStatus.Caption = "Mando messaggio"
    MSComm1.Output = "Distributore fuori servizio, corri!!"
    timerPause.Enabled = True
    Do While timerPause.Enabled = True
        DoEvents
    Loop
    For I = 1 To 2
    NelBuffer = ""
        lblStatus.Caption = "Mando ritorno a capo n. " & I
        MSComm1.Output = vbCr
        chiamante = "CR"
        timerPause.Interval = 1000
        timerPause.Enabled = True
        Do While timerPause.Enabled = True
            DoEvents
        Loop
    Next I
    lblStatus.Caption = "Chiudo Tutto"
    MSComm1.Output = "ATH0"
    MSComm1.PortOpen = False
    Close #FF2
End Sub
e poi il timer
Private Sub timerPause_Timer()
    Dim Posizione As Integer
    lblStatus.Caption = "TimerPause Attivato"
    If chiamante = "SendAMessage" Then
        If Contatore = 15 Then GoTo NoAnswer
        lblStatus.Caption = "Buffer vuoto, attendo"
        If MSComm1.InBufferCount = 0 Then Contatore = Contatore + 1: Exit
Sub
        'Contatore = 0
        timerPause.Enabled = False
        NelBuffer = NelBuffer & MSComm1.Input
        Print #FF2, NelBuffer
        'Valuta le risposte possibili
        Posizione = InStr(1, NelBuffer, "NO CARRIER")
        If Posizione <> 0 Then
            lblStatus.Caption = "NO Carrier"
            timerPause.Enabled = False
            GoTo NoCarrier
            'ClosePrg
        End If
        Posizione = InStr(1, NelBuffer, "NO DIALTONE")
        If Posizione <> 0 Then
            lblStatus.Caption = "NO DialTone"
            timerPause.Enabled = False
            GoTo NoCarrier
        End If
        Posizione = InStr(1, NelBuffer, "ERROR")
        If Posizione <> 0 Then
            lblStatus.Caption = "ERRORE"
            timerPause.Enabled = False
            GoTo NoCarrier
        End If
        Contatore = 0
        txtCom.Text = txtCom.Text & vbCrLf & NelBuffer
    End If
    If chiamante = "CR" Then
        Contatore = Contatore + 1
        If Contatore = 12 Then GoTo NoAnswer
        If MSComm1.InBufferCount = 0 Then Exit Sub
        timerPause.Enabled = False
        NelBuffer = MSComm1.Input
        txtCom.Text = txtCom.Text = NelBuffer
    End If
    If chiamante = "NoCarrier" Then
        ContaNoCarrier = ContaNoCarrier + 1
        lblStatus.Caption = "Ho chiamato " & ContaNoCarrier & " volte"
        timerPause.Enabled = False
        If ContaNoCarrier = 4 Then
            Ripeti = False
            lblStatus.Caption = "Nessuna Risposta"
            Print #FF2, "Nessuna risposta dopo 4 tentativi"
            Exit Sub
        End If
        SendAMessage
        Exit Sub
    End If
'Inserire codice per la non risposta della com
NoAnswer:
    Ripeti = False
    lblStatus.Caption = "No answer"
    Print #FF2, "Routine No Answer"
    Exit Sub
NoCarrier:
    lblStatus.Caption = "No Carrier"
    Print #FF2, ("Routine No Carrier" & vbCrLf)
    chiamante = "NoCarrier"
    timerPause.Interval = 20000
    MSComm1.PortOpen = False
    Ripeti = True
    Exit Sub
End Sub
Ciao... Maurizio

 L'hai voluta tu :-)))
[cut]
Hai ragione. Mi arrendo.
Senza indentazione e con tutti i GoTo, č impossibile capire qualcosa.
Ci ho provato, e non ho trovato niente di particolare.
Io la stessa cosa l'avrei fatta con l'evento OnComm, forse era *un pochino*
piů leggibile...
Ciao
Alberto

 Quale sarebbe il secondo ciclo?
...
Come dicevo, la routine che fa la chiamata viene eseguita una volta, se il
codice nel timer vede che e' stata ricevuta una stringa contenente "NO
CARRIER", di riattivare il timer (se stesso)  e di uscire da quello che sta
facendo(in timerPausa.... Exit sub) .
Dopo un intervallo di 20 secondi, il TimerPause si riattiva, vede che una
variabile e' stata settata per il rilancio della sub chiamante stessa. In
pratica, e forse questo potrebbe essre un problema, la Sub chiamata (il
timer) chiama la chiamante.
Vabbe', sono un po' arzigogolato... Devo imparare un po' su come ordinare le
cose.
Ciao (per ora)... Maurizio

 tu, ma almeno non freeze l'applicazione
...
Si, ho sbagliato ad esprimermi io.
Non rispondo alle altre tue domande perche' *forse* ho risolto. Se e' cosi',
fra qualche minuto lo sapro' e postero' la soluzione....
Ma guarda tu, uno cerca un aiuto da un ng di esperti e la soluzione se la
deve trovare da solo :-)))))))
Graaaaazie a tutti!!!!
P.s.
Ma, per caso, Iw7 vuol dire che sei in Puglia?
Se e' cosi', ciao da IZ0 ;-)


 più leggibile...
...
Ehmm.... io ho preso spunto da un altro progetto che ho trovato, l'OnComm
non lo conosco molto, pero' e' uno spunto per studiarlo.
Ciao... Maurizio

 Dopo un intervallo di 20 secondi, il TimerPause si riattiva,
Se č disabilitato, come fa a misurare i 20 secondi?
Ho guardato (con fatica) il codice, senza approfondire piů di tanto.
Ho visto che piů volte disabiliti il timer ed esci, sicuro che questo sia
corretto?
Io metterei un timerPause.Enabled=False in testa alla Sub timerPause_Timer
e, magari aiutandomi con dei segnali, lo riattiverei all'uscita (da
concentrare in un punto preciso, quindi sostituendo tutte le Exit Sub).
In questo modo sei sicuro che il timer non scatta un'altra volta mentre
ancora sta eseguendo le istruzioni del ciclo precedente.
Ho visto anche che chiami SendAMessage... non mi piace, mi sa tanto di
ricorsione, indipendentemente dallo scatto del timer.

 ricorsione, indipendentemente dallo scatto del timer.
...
Cosa e' una ricorsione?
Grazie e ciao.... Maurizio

 Cosa e' una ricorsione?
Una roba che chiama se stessa.
A volte il gatto che si morde la coda sente un male boia, ma non sa come
fermarsi.
Il tuo evento timerPause_Timer a un certo punto chiama la SendAMessage e
questa, a un certo punto, lascia che scatti lo stesso evento...

 Se e' cosi', ciao da IZ0 ;-)
73 de iw7pcg op. Dante


 73 de iw7pcg op. Dante
...
73 de iz0eso sk sk

....
Dunque, mi rispondo da solo, potrebbe essere utile a qualcuno e comunque e'
un modo per ringraziare chi mi ha aiutato.
Probabilmente, come diceva Lupo, potrebbe essere un problema di routine che
si chiamano tra di loro; il gatto che si morde la coda!
Ho messo un altro timer che fa tutte le chiamate, ora funziona :-)
Ciao... Maurizio

 più leggibile...
...
Ciao Albe V°,
ho provato a vedere cosa accadeva con l'evento OnComm, ma ho visto che
questo viene scatenato solo quando (nel mio caso), il modem remoto risponde;
in questo caso la propieta' MSComm1.OnEvent = 5.
Come avrei potuto sfruttare l'OnComm per controllare il flusso dei dati?
Ciao... Maurizio


Hai impostato RThreshold a 1?
Ciao
Alberto

 Hai impostato RThreshold a 1?
...
No, ma posso provare :-))
Per ora ho messo, nell'evento OnComm, una istruzione che mi va ad aggiornare
la caption di una label e un'istruzione Print che va a scrivere in un file
di log i codici di eventi/errori che scatenano l'evento.
Provo a settare RThreshold a 1 e vedere cosa succede.
Bye... Maurizio

 Hai impostato RThreshold a 1?
...
Fatto...
Oltre al codice 5 (MSComm1.CommEvent = 5), mi viene restituito un 2 per ogni
carattere ricevuto.
Non viene, per esempio, dato un codice quando e' finita la stringa o altro.
E' vero che potrei, ad esempio, esaminare ad ogni evento OnComm una stringa
data da quello che era presente nel buffer, pero' forse e' una strada
impegnativa. Anche perche' non ho la certezza che un invio a capo
corrisponda alla fine della stringa.... A meno che non ci sia un carattere
che indica la fine della stringa; in quel caso......
Il vantaggio rispetto all'uso del timer lo vedo solo nell'immediatezza
dell'evento. Mi spiego, con l'evento OnComm avrei immediatamente la risopsta
di quando il buffer si sta riempiendo, mentre con il timer devo aspettare
che questo scatti, magari avendo dei tempi morti tra il momento che il
buffer ha ricevuto tutto e il momento che scatta il timer. Impostando pero'
l'intervallo del timer basso, diciamo sul secondo, questo ritardo sarebbe
trascurabile.
Ciao.... Maurizio


Il dover utilizzare una stringa dove conservi i vecchi caratteri arrivati e
aggiungi i nuovi è una cosa da fare anche se utilizzi un timer.
Se non lo hai mai fatto, e ti è andata sempre bene, è solo puro culo.
La seriale è asincrona.
Ciao
Alberto

 Se non lo hai mai fatto, e ti è andata sempre bene, è solo puro culo.
...
Beh, almeno ogni tanto nella vita. :-)))
In effetti, la variabile da aggiornare in continuazione l'ho usata quando mi
e' servito di sapere esattamente cosa mi stava dicendo la seriale. Il bello
era che, in quel caso, avevo un carattere che mi diceva quando la stringa
iniziava e quando finiva.
Nel caso di oggi, non mi interessa sapere cosa mi sta dicendo la seriale,
pero' dando un tempo abastanza lungo al timer, ho la certezza che il tutto
il messaggio di ritorno sia stato ricevuto.
Ciao... Maurizio

 certezza che il tutto il messaggio di ritorno sia stato ricevuto.
Se il tempo è fissato nel codice, tu hai una certa probabilità di avere
ricevuto tutto il messaggio di ritorno, non la certezza.
E la prima volta che ti manca un byte, ti si sfasa tutto, e finchè non
resetti sei in palla.
Ciao
Alberto

 ricevuto tutto il messaggio di ritorno, non la certezza.
...
In questa mia appicazione non e' necessario avere una certa precisione;
questo non e' un buon motivo per fare le cose approssimative, quindi ti
ringrazio ti tutti i suggerimenti che mi stai dando....
Io, ricevendo una serie di caratteri, non so esattamente quando l'operazione
e' stata conclusa.
Come faccio a sapere se il modem trasmittente mi ha inviato tutti i
caratteri?
C'e' un carattere (immagino diverso dal ritorno a capo) che mi indichi....
"ok, ho finito"?
Purtroppo, valutando l'evento OnComm, non ho visto nulla.
Ciao.... Maurizio

 indichi.... "ok, ho finito"?
C'è praticamente sempre. Oppure il pacchetto è a lunghezza fissa.
Dipende da ciò con cui comunichi.
Ciao
Alberto

 Dipende da ciò con cui comunichi.
...
In questo caso sto comunicando con il Centro servizi Telecom per l'invio di
SMS.
Che tipo di collegamento sto facendo (e potresti rispondermi... se non lo
sai tu!! :-)) ? Il protocollo e' lo ZModem? In quel caso, se e' previsto in
questo protocollo un carattere di fine trasmissione, potrei andare a
cercarmi un po' di documentazione!
Ciao... Maurizio

 non lo sai tu!! :-)) ?
Stai chiedendo a me che collegamento stai facendo tu?
E cosa cavolo ne so.
La seriale può comunicare con qualcosa tipo due/tre milioni di diverse
periferiche/host/apparecchiature, teoricamente ognuna con un suo protocollo.
Io ne avrò usati al massimo 50-60, per gli altri n milioni credo che ognuno
si debba informare...
Ciao
Alberto

 Stai chiedendo a me che collegamento stai facendo tu?
....
Beh, lo avevo anticipato :-)))
Ti chiedo pero' un lume.
Come ho gia' spiegato, tramite modem e comandi AT, sto chiamando un altro
modem (SMSC) di Telecom.
Lo stesso procedimento che io ho automatizzato, puo' essere fatto tramite
Hyperterminal.
Immagino che i due Modem comunichino tra loro tramite un protocollo che
*credo* sia il ZModem. Ti risulta?
Se cosi' fosse, per sapere quando il mio corrispondente ha terminato di
trasmettere le sue informazion, io devo intercettare un carattere che nel
protocollo ZModem vuol dire "Fine", oppure dovrei intercettare un carattere
che viene generato dal MIO modem che mi dice che LUI (il modem stesso) ha
ricevuto un segnale di fine?
Grazie... Maurizio

 che *credo* sia il ZModem. Ti risulta?
Non ne ho veramente la più pallida idea.
Ma tu cerchi di comunicare con qualcuno/qualcosa senza aver chiesto il
protocollo?
Ciao
Alberto

 protocollo?
...
Gia', ma dovrebbe essere standard.
Hyperterminal non mi fa nessuna storia.
Ciao... Maurizio