Controllo TIMER

lunedì 20 giugno 2016 - 14.59

emanuele1111 Profilo | Newbie

Salve a tutti,
un consiglio:

nel mio sw, VB2013, nell'evento in cui ricevo un barcode sulla seriale ---> "Private Sub UpDateText(ByVal [text] As String)" , avrei necessità di controllare che ENTRO 60ms la procedura abbia terminato di fare ciò che deve.
Se questo tempo viene superato avvisare l'utente con un msg.

Ho provato ad usare il controllo Timer ma, l'evento TICK, me lo esegue a fine procedura anche se lo START lo faccio a monte della stessa.

Non è forse questo il metodo esatto?

Attendo vs.

ysdemarc Profilo | Expert

L'evento è corretto.

Hai controllato di aver impostato l'intervallo correttamente in millisecondo (60 * 1000) ed che effettivamente attivi il timer col metodo Start?

emanuele1111 Profilo | Newbie

Si ho controllato ed è tutto esatto.
Il problema è che il Timer di x se, da partire il TEMPO al .START quando è terminata la procedura nella quale c'è anche lo .START, invece a me serviva controllare proprio che entro un intervallo di tempo ce la facesse o meno la procedura a fare delle operazioni.
Ma se lo .START parte alla fine della procedura stessa non ha senso..... spero di essermi espresso bene....

Fammi sapere per favore

ysdemarc Profilo | Expert

Scusami ma non ho compreso tanto bene quello che hai scritto.

Se a te serve controllare che lì'utente ci stia solo 60 secondi dall'inizio del caricamento del form, già nell'evento Load o Shown potresti avviare il timer.

Se invece ti serve controllare il tempo dopo che magari ha fatto Salva, avvii lo Start li.

Se devi controllare più tempi di quello che succede puoi anche utilizzare più timer.

In alternativa, se non vuoi utilizzare un timer potresti crearti una funzione di attesa tipo questa:

private void Wait(int secondi) { int secPass = 0; int secTime = System.DateTime.Now.Second; if (secondi == -1) secPass = -1; while (secPass <= secondi) { int ss = System.DateTime.Now.Second; if (secTime != ss) { if (secondi != -1) secPass++; secTime = System.DateTime.Now.Second; } Application.DoEvents(); } }

Tutto sta a quello che ti serve cdi cui purtroppo leggendoti non ho compreso bene.

emanuele1111 Profilo | Newbie

Ciao cerco di spiegarmi meglio:
io leggo sulla seriale un barcode,
appena leggo il barcode devo interrogare il db e vedere se lo trovo in Tabella;

Questo tempo di richiesta al db e relativa risposta deve avvenire entro 30ms,
altrimenti devo agire di conseguenza, ma in questa stessa routine, cioè se il db a rispondermi ci mette 20 secondi io appena terminano i 30ms devo agire senza attendere i 20 secondi.

Naturalmente per ogni lettura di barcode devo fare questo controllo.

Spero di essermi fatto capire meglio.

ysdemarc Profilo | Expert

Allora ti fai una variabile a livello di modulo che ti restituisca lo stato dell'elaborazione del barcode che potrai valorizzare direttamente mentre elabori oppure da avere come falore di ritornoi a fine elaborazione.

Questa variabile la interroghi nell'eventi Tick:

se hai superato i 60 secondi e la variabile non ha avuto un risultato di fine elaborazione dai il tuo avviso.

Se intenti anche interrompere l'elaborazione ovunque sia arrivata potresti fare un boolean a livello di modulo (blnInterrompi) inizializzata a false e superando i 60 secondi, quando dai l'avviso la metti a true.

Questa interrogata all'interno delle tue elaborazioni servirà a fare un break anticipato.

Se le elaborazioni avvengono in oggetti che non vedono la tua variabile blnInterrompi, gliela puoi sempre passare in chiamata per riferimento con ref

Naturalmente è una soluzione che potrebbe andare bene ma il tutto sta da come hai strutturato lo sviluppo e l'appilicazione.

Potresti anche considerare se l'elaborazione la fai in oggetti diversi da quello della chiamata di crearti i delegate e gli eventi per restituirti lo stato dell'elaborazione e passare eventuali valori per l'interruzione

emanuele1111 Profilo | Newbie

Ciao,
ci avevo pensato ed ho provato a fare cosi:
in un campo textbox mi setto un valore 1 alla partenza della lettura del barcode che diventa 2 quando la procedura è finita,
faccio partire lo .START con 60ms, il problema è che nell'evento tick del TIMER dove verifico se nella textbox ci sia 1 oppure 2 me lo esegue quando ha terminato la routine quindi c'è sempre 2 anche nel caso in cui, ad interrogare il db e a restituirmi il risultato ci abbia messo meno di 60ms e quindi dovrei trovare la casella di testo settata ad 1.

Come gestiresti te la cosa?

ysdemarc Profilo | Expert

Hai sicuramente impostato male il Timer e comunque lo Start devi avviarlo prima della lettura del barcode, e durante le elaborazioni un DoEvents non gli farà di certo male.

Magari è proprio nell'impegno di risorse che non riesce a scatenare l'evento Tick

Controlla bene, sicuramente c'è una sciocchezza che ti sfugge

emanuele1111 Profilo | Newbie

Quindi seconde te cosi dovrebbe funzionare:
1) setto textbox = 1
2) leggo il barcode dalla seriale
3) .START (60ms)
4) interrogo db e ricevo risposta
5) setto textbox = 2
6) fine procedura

se dal punto 3) che fa lo .START alla fine del punto 4) impiega più di 60ms devo uscire, interrogando nell'evento TICK il valore che trovo in textbox che dovrebbe essere = 1. (è che purtroppo c'è sempre 2 scritto perchè ho paura che il Timer parta dopo il punto 6)

Sei d'accordo?

ysdemarc Profilo | Expert

a prescindere che a fine procedura sarebbe anche opportuno usare il metodo Stop

Comunque se nella textbox hai 2 forse lo cambi da qualche altra parte.

Se ne vuoi la sicurezza imposta Interval a 1000 (1 secondo) ti fai una variabile globale che ti tiene il conto di quante volte entra in Tick e quindi quanti secondi sono se la variabile raggiunge 60 fai le tue considerazioni sull'interruzione forzata.

Ogni volta che entra in Tick prova a scrivere qualcvosa o a stampare il tempo nella form e vedi se sta contando..

magari potresti partire da 60 a decremetare e fornire anche visivamente questa informazione all'utente.

Poi piuttosto che usare una textbox io userei una variabile boolean, usdando le stringhe quello che visivamente ti sembra 2 potrebbe non esserlo.

emanuele1111 Profilo | Newbie

ok proverò e ti faccio sapere

alextyx Profilo | Expert

Premesso che la precisione di un timer non dovrebbe essere presunta superiore ad alcune decine di millisecondi, io suggerisco semplicemnete di scivere in una variabile DATE il momento in cui vorresti dare lo start la timer (che invece se serve solo a questo io eliminerei completamente) e poi, in alcuni punti chiave, potresti confrontare il DATE.NOW con quello memorizzato. Se la differenza eccede i 60ms (e qui la vedi con una discreta precisione), prendi le misure che ti servono. Il problema è capire se puoi effettivamente impostare dei punti controllo dell'ora raggiunta (il DATE.NOW, appunto). Se invece la tua procedura deve essere interrotta da una che viaggia in autonomia, ovvero quella che nelle intenzioni sarebbe stata la routine del timer, potresti innescare una procedura eseguita su un thread autonomo, con un backgroundworker, alla quale potresi passare il DATE contenente il momento di inizio del conteggio. Con un loop potresti controllare il tempo passato e se entro i fatidici 60 ms una variabile accedibile non le dice che il lavoro è stato completato, attraverso tale procedura prenderai le tue contromisure.
La logica che ti suggerisco la adotto in un programma per cartellonistica digitale, dove vengono eseguiti alcuni palinsesti di contenuti grafici ognuno dei quali va tolto tolto di programmazione dopo un certo tempo, o comunque si deve controllare, nel caso di filmati, che siano giunti a conclusione entro il tempo massimo previsto.

emanuele1111 Profilo | Newbie

Ciao è proprio così,
è il secondo caso che hai esposto quello che mi serve.

Hai un esempio di come poter fare con i thread?

Io entro 60 ms devo dare una risposta, indipendentemente da quanto tempo la procedura impieghi a terminare.

Fammi sapere se puoi grazie

alextyx Profilo | Expert

Io stesso mi basai su degli esempi trovati in rete per implementare dei backgroundworker. Ci sono pochi concetti fondamentali che devi usare e sei a posto. Ti conviene cercare con Google, notizie sulla natura e l'uso del backgroundworker. Guardo intanto se ritrovo qualcosa anche io.....
Ecco, ho recuperato qualche link:

http://forum.masterdrive.it/visual-basic-net-18/backgroundworker-thread-separato-47364/

http://www.pierotofy.it/pages/guide/Guida_al_Visual_Basic_dotNET/BackgroundWorker_e_FileSystemWatcher/

https://msdn.microsoft.com/it-it/library/ywkkz4s1.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-1

Da un pezzo non ci metto gli occhi sopra, ma mi ricordo che con un minimo di attenzione e qualche fase di apprendimento per errore/correzione, in pochissimo tempo questo componente ti mette in condizione di lavorare con i thread senza particolare sforzo.

Vediamo se con questo riesci a fare un passo avanti per la soluzione. Poi, sui 60ms io non ci farei grandissimo affidamento comunque. Però secondo me ti ci avvicinerai abbastanza. Per vederlo potresti far andare in timeout la procedura e far stampare un messaggio che indica, tutte le volte, la differenza in millisecondi rilevata al momento che viene deciso di procedere per il recupero o per dare l'allarme o per quella che sarà la tua azione. Ovviamente troverai tutti numeri > 60 e se alla fine non ti capiterà quasi mai di vedere numeri superiori a 90, direi che potrai ritenerti soddisfatto. Credo che di meglio sia difficile anche con i multimedia timer che mi pare di aver usato in una occasione, ma per qualche motivo non rimasi impressionato più di tanto. VB non è linguaggio per lavorare coi millisecondi

emanuele1111 Profilo | Newbie

Appena ho un attimo di tempo proverò e vi aggiorno.

Grazie e buon lavoro a tutti
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5