[VB 2013] Consiglio su come utilizzare più Timer

martedì 17 febbraio 2015 - 19.34
Tag Elenco Tags  VB.NET  |  .NET 4.0  |  Windows 7

giamisan Profilo | Newbie

Ciao a tutti, vi scrivo perchè come da oggetto avrei bisogno di un consiglio su come gestire nel miglior modo possibile il mio problema:

mi ritrovo con una Datagrid all'interno della quale vi è una colonna di tipo DataGridViewCheckBoxColumn.
Il numero delle righe della Datagrid non è prevedibile all'avvio del programma perchè può essere che in fase di esecuzione debba aggiungere / togliere delle righe.
Quando la CheckBoxCell della relativa riga è TRUE devo inizializzare un timer che ad un certo orario scrive in un file dei dati. Il percorso del file e i dati da scrivere sono indicati nelle altre celle della riga

Pertanto i miei problemi sono 2:

1) Non sapendo a priori quanti Timer dover creare come faccio a fare in modo che il Timer creato dalla riga 1 scriva nel percorso indicati in riga 1 i dati indicati nella stessa e non in un altra riga?
2) Nel caso in cui io abbia attivato più Timer e ad un certo punto decido di eliminare una riga della DataGrid mentre il Timer è ancora attivo, come faccio a stoppare e fare il Dispose sul Timer corretto?


Io avevo pensato di crearmi una Struttura del tipo:

Structure TableTimer
Public ID as Interger
Public t as Timer
Public percorso as String
Public dati as string
End Structure

Il campo ID sarebbe una sorta di chiave primaria che inserisco con il numero della riga della datagridview in modo tale da poter recuperare velocemente il Timer nel caso in cui decida di eliminare la riga dalla DataGrid.

Qualcuno ha un consiglio migliore da darmi?

Scusate se per alcuni la soluzione potrebbe esser semplicissima ma talvolta mi rendo conto che per arrivare al mio obiettivo intraprendo la strada più complessa e più dispendiosa in termine di risorse del computer per poi rileggere il codice funzionante e accorgermi ch avrei potuto ottenere il medesimo risultato scrivendo 1/10 delle righe di codice che ho scritto!!!

Grazie a tutti per l'aiuto.....

AntCiar Profilo | Expert

Ciao. Vorrei chiederti maggiori delucidazioni su :

>Quando la CheckBoxCell della relativa riga è TRUE devo inizializzare
>un timer che ad un certo orario scrive in un file dei dati.

Non riesco a capire cosa intendi per "ad un certo orario":

- se intendi che alle ore X realtive all'orologio di sitema devi eseguire l'azione, allora non ti servono N timer ma ne basta uno solo. Nella sorgente dati della gridView devi avere anche un campo in cui memorizzi l'ora o l'intervallo delle ore nelle quali eseguire l'azione. Imposti il valore di Interval al valore di "sensibilità" che vuoi. Tipo ad esempio lo puoi impostare a 1 secondo (1000) oppure a un minuto (60000) e all'interno dell'evento Tick del timer ti scorri le righe e prendi in considerazione solo quelle con il valore del check a true. Se l'ora di sistema è nell'intervallo richiesto, esegui l'azione altrimenti aspetti...

- se intendi che ogni X tempo deve eseguire l'azione allora puoi fare nel seguente modo: nella sorgente dati della griglia ti metti due campi in più in cui in uno inserisci il valore del tempo che vuoi controllare espresso nell'unità di conteggio del timer, mentre l'altro lo inizializzi a 0 (lo usi come un counter). Ti crei un solo timer impostando il valore di Interval corretto e nell'evento Tick ti scorri le righe della griglia e prendi in considerazione solo quelle con il check a true. Per queste righe incrementi il valore del campo counter di 1 e poi controlli se questo valore è uguale o superiore al valore impostato da te. Se è così allora esegui la tua azione e poi azzeri il counter per il prossimo giro.

Cristian Barca

giamisan Profilo | Newbie

Ciao Cristian....forse in effetti sono io che non mi sono spiegato in modo adeguato. Ti faccio un esempio molto più pratico con una Datagrid popolata da 3 righe, le cui celle sono:

Cella 0 = contiene il check box
Cella 1 = contiene l'orario di attivazione (lo inserisco io a mano)
Cella 2 = contiene il percorso del file su cui scrivere
Cella 3 - 4 - 5 -6 = contengono i dati da scrivere nel file il cui percorso è specificato in Cella 2

Ora, dobbiamo considerare che:

1) DI default i check box sono impostati su Unchecked
2) L'orario di attivazione non è lo stesso per ciascuna riga perchè ogni file deve esser scritto in orari diversi
3) La scrittura nel file deve essere effettuata solo se il check box è Checked
4) Avendo come da esempio 3 righe nella datagrid non è detto che tutti e 3 i check box siano Checked, potrebbe esser soltanto 1, soltanto 2, tutti e 3 o nessuno

In considerazione del punto 4 nasce la mia idea di creare un Timer per ogni riga Checked, ognuno con il proprio orario di attivazione preso dalla relativa cella 1.

A livello di codice, non ho alcun problema a creare un nuovo Timer nel momento in cui ogni checkbox diventa Checked ma il mio problema è che ogni volta che si verifica l'evento Tick non riesco a fare un distinzione se l'evento è stato generato dal Timer della prima riga piuttosto che da quello della seconda e questo è il mio primo problema perchè è pur vero che alla fine devo sempre scrivere dei dati in un file ma a seconda dei dati presenti nelle celle 3-4-5-6 devo o non devo fare delle operazioni prima di scrivere nel file.

Inoltre, supponendo di avere diversi Timer attivi nello stesso momento e decidendo di eliminare una riga dalla Datagrid o disattivare il relativo Timer come faccio ad eliminare / disattivare il timer giusto?


Ieri sera ci ho pensato e mi è venuta in mente un'altra possibile soluzione:
- Credo un'apposita classe che oltre a crearmi un oggetto Timer mi espone una proprietà univoca che mi permette di capire se l'istanza di quella classe è relativa alla riga 0 piuttosto che alla riga 1
- in questo modo ogni volta che attivo la check box creo un'instanza della classe (es 3 check box attive = 3 istanze della stessa classe). Ma non sono sicuro poi di riuscire a fare il Dispose sull'istanza corretta....

Ora provo....

Cosa ne dici?

AntCiar Profilo | Expert

vedo inutile la creazione di N timer perchè sono sprecati.

Vedo anche errata questa tua considerazione:

"In considerazione del punto 4 nasce la mia idea di creare un Timer per ogni riga Checked, ognuno con il proprio orario di attivazione preso dalla relativa cella 1"

in quanto un timer si usa principalmente per scandire il tempo all'intero di un oggetto e non per "attivarsi" ad un certo tempo.

Per me la cosa più semplice è questa:

ti crei un timer sulla form e imposti il valore desiderato di interval (dipende dalla precisione che vuoi)

nell'evento Tick ti scorri le tue righe e se sono con il check a true, valuti se l'orario inserito è minore o uguale a quello di sistema. Se verificata la condizione, esegui quello che devi fare e poi imposti il check a false altrimenti ai prossimi click si ripeterà l'azione.
Cristian Barca

giamisan Profilo | Newbie

Ok perfetto ho capito, adesso ho capito benissimo quello che tu intendi dirmi ed in effetti la soluzione è molto più semplice di quello che pensavo!!! (come avevo detto fin dall'inizio!!!9

Adesso ti faccio però un'altra domanda!! hihihi

Visto che il programma girerà per 8/9 ore al giorno e quindi il Timer potrebbe essere attivo per il medesimo tempo,
Visto che i file da scrivere potrebbero essere 2 o anche 10 ad orari diversi
Visto che l'orario di attivazione è espresso in hh:mm:ss (per cui ho bisogno di precisione massima) dovrei mettere un intervallo veramente piccolissimo sull'evento Tick (per esempio 1 secondo)


Secondo te non risulterebbe troppo pesante (in termini di prestazioni) continuare a ciclare una datagrid ogni secondo tenendo presente che nelle stesse celle della datagrid vengono contemporanmente scritti altri dati da altre Sub?

AntCiar Profilo | Expert

Un timer che "clocca" ogni secondo non è un problema. Il problema sta nell'eventuale azione che deve fare ogni secondo.

Per ovviare al problema di dover scorrere ogni secondo la lista puoi risolvere in questo modo:

dichiarati una lista di DateTime nella tua form

private TimeList As Generic.List(Of DateTime) = New Generic.List(Of DateTime)()


poi ogni volta che attivi una voce della griglia aggiungi la data/ora di controllo nella lista e subito dopo ordina la lista:

TimeList.Add( ...oggetto datetime rappresentante l'ora di "scatto" della riga .... )
TimeList.Sort()


Se disattivi una riga, scorri TimeList e cerca il primo valore di dataora uguale a quello della riga disattivata e rimuovilo (mi raccomando solo la prima occorrenza) e poi riordina la lista.


Facendo così avrai una lista ordinata in modo crescente di date/ora.

All'interno dell'evento tick del timer controlla se TimeList.Count > 0 e la dataora di sistema Date.Now è maggiore o uguale al primo elemento della tua lista. In caso affermativo allora inizia a scorrere la griglia cercando il valore di dataora uguale a quello della TimeList(0) e che ha il check a true ed esegui le tue operazioni (magari se le lanci in un thread a parte sarebbe meglio). Dopo aver fatto le tue operazioni metti il check a false ed elmina l'elemento TimeList(0) dalla lista.

if Date.Now >= TimeList(0) Then
...
...
...
end if


Sempio pratico (le righe rappresentano valori con il check gia a true)


18/02/2015 13.00.00 A
18/02/2015 10.00.00 B
18/02/2015 10.30.10 C
18/02/2015 12.25.00 D
18/02/2015 16.00.00 E
18/02/2015 16.00.00 F


in TimeList ci saranno le date ordinate in ordine cronologico

(0) 18/02/2015 10.00.00
(1) 18/02/2015 10.30.10
(2) 18/02/2015 12.25.00
(3) 18/02/2015 13.00.00
(4) 18/02/2015 16.00.00
(5) 18/02/2015 16.00.00

Supponiamo che l'orologio di sistema segna le ore 08.30.10
ad ogni evento tick del timer controlli:

if TimeList.Count > 0 Then

if Date.Now >= TimeList(0) Then
''scorri la lista e cerchi l'elemento con la data/ora = TimeList(0) e con check = true
''esegui le tue operazioni utilizzando la riga trovata
''rimuovi la data in posizione 0 da TimeList: TimeList.RemoveAt(0)
''togli il check dalla riga in modo da non riprocessarla piu

end if
end if

Fino a che l'orologio di sistema non arriva (o non supera) alle ore 10.00.00 non viene fatto nessun controllo. Alle 10.00.03 sicuramente avrai eseguito la riga in questione e avrai tolto l'orario dalla lista. In questo modo negli istanti successivi il timer pur scatenandosi non va a fare controlli inutili sul datagrid perchè 'sa' che fino alle 10.30.10 non dovrà fare niente.











Cristian Barca

giamisan Profilo | Newbie

Grazie infinite Cristian!!!

Per ora ho messo in atto la tua prima soluzione e direi che funziona benissimo, ovviamente non lo sto facendo andare a ragime per cui non posso dire come lavorerebbe con molti più orari da controllare....

Ad ogni modo, in un'ottima di migliorare le prestazioni metterò sicuramente in atto la tua ultima idea perchè mi sembra la più performante e logica!!!


Grazie ancora tantissimo!!!
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-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5