2010-03-12 15 views
10

Stiamo riscontrando il seguente problema durante l'utilizzo di System.Threading.Timer (.NET 2.0) da un servizio Windows.Timer C# che viene generato prima dell'intervallo

  1. Ci sono circa 12 diversi oggetti di timer ..
  2. Ogni timer ha il tempo e l'intervallo dovuto. Questo è impostato correttamente.
  3. Si osserva che dopo 3 o 4 ore, i timer iniziano a segnalare prima dell'intervallo. Ad esempio, se il timer dovrebbe segnalare alle 4:59:59, viene segnalato alle 4:59:52, 7 secondi prima.

Qualcuno può dirmi qual è la causa di questo comportamento e qual è la soluzione?

Grazie, Swati

risposta

0

Forse riprogrammazione è fatto dopo un'operazione che richiede alcuni secondi per completare. O non controlli questo?

0

Questo non può essere controllato in quanto dipende dalla velocità del sistema, se si dispone di un computer super allora potrebbe non esserci abbastanza differenza, ma se si dispone di un PC normale allora ci sarà differenza nell'intervallo del timer dopo molto tempo esecuzione.

Spero che possa essere d'aiuto.

9

Grande domanda ... ed ecco la ragione:

"Timing" è una cosa difficile quando si tratta di computer ... si può mai contare su un "intervallo" per essere perfetto. Alcuni computer "scandiscono" il timer solo ogni 14-15 millisecondi, alcuni più frequentemente, meno frequentemente.

Quindi:

Thread.Sleep(1); 

Potrebbe richiedere da 1 a 30 millisecondi per l'esecuzione.

Invece, se hai bisogno di un timer più preciso - devi catturare il DateTime di quando inizi, e poi nei tuoi timer dovresti controllare sottraendo DateTime.Ora e l'ora originale per vedere se è " tempo di eseguire "il tuo codice.

Ecco qualche esempio di codice di ciò che devi fare:

DateTime startDate = DateTime.Now; 

Quindi, avviare il timer con l'intervallo impostato a 1 millisecondo. Quindi, nel tuo metodo:

if (DateTime.Now.Subtract(startDate).TotalSeconds % 3 == 0) 
{ 
    // This code will fire every 3 seconds. 
} 

Il codice sopra farà fuoco fedelmente ogni 3 secondi. Puoi lasciarlo in esecuzione per 10 anni e continuerà a sparare ogni 3 secondi.

+0

So che è solo un esempio, ma non aumentereste l'intervallo del timer a qualcosa come 100 o addirittura 500 msec? So che potresti perdere un po 'di precisione, ma non sarebbe meglio che avere un timer acceso 1000 volte al secondo quando hai bisogno di un risultato ogni 3 secondi? –

6

La spiegazione di Timothy è convincente, ma System.Threading.Timer funziona già in questo modo. Almeno nell'implementazione di Rotor, utilizza il valore restituito da GetTickCount() per calcolare quando è previsto il prossimo callback. Non è molto probabile che anche il CLR reale lo faccia, è più probabile che usi CreateTimerQueueTimer(). Tuttavia, è probabile che anche questa funzione API dipenda dal tick interno incrementato dall'interrupt tick tick.

Il problema è quanto bene funziona il clock interno (restituito da GetTickCount() e Environment.TickCount) rimane sincronizzato con il tempo assoluto del muro (restituito da DateTime.Now). Sfortunatamente, questo è un dettaglio di implementazione dell'HAL sulla tua macchina, l'Hardware Abstraction Layer. Il costruttore di macchine può fornire un HAL personalizzato, uno che è stato ottimizzato per funzionare con il BIOS e il chipset della macchina.

Mi aspetterei problemi se la macchina ha due sorgenti di temporizzazione, un chip di clock che è stato progettato per tracciare il tempo di parete e continua a ticchettare anche se si scollega la potenza della macchina, e un'altra frequenza disponibile sul chipset che può essere divisa in fornire l'interruzione dell'orologio. Il PC IBM AT originale funzionava in questo modo. Di solito, il chip dell'orologio può essere considerato attendibile, l'orologio sarebbe gravemente fuori se non è preciso. Il chipset non può, tagliare gli angoli sulla qualità degli oscillatori è un modo semplice per risparmiare un centesimo.

Risolvi il problema evitando lunghi periodi di tempo sul tuo timer e ricalcoli il prossimo tempo a partire da DateTime.Ora nel callback.

+0

Grazie per il vostro aiuto. Il ricalcolo dei timer può risolvere il mio problema. Ci proverò. Grazie ancora !! –

Problemi correlati