Aumenta l’evento in intervalli / timer ad alta risoluzione

Voglio usare il timer di risoluzione più alto ansible usando c #. Ad esempio, voglio aumentare un evento ogni 11 tick (ho sentito che tick è il contatore più alto ansible nel pc). Ho provato il timer e ho scoperto che il tempo minimo trascorso è in millisecondi. Ho guardato il cronometro ma il cronometro non genera eventi.

Grazie.

L’utilizzo di un timer multimediale dovrebbe fornire circa 1000 eventi al secondo. Questo codice dovrebbe aiutarti per strada.

public delegate void TimerEventHandler(UInt32 id, UInt32 msg, ref UInt32 userCtx, UInt32 rsv1, UInt32 rsv2); ///  /// A multi media timer with millisecond precision ///  /// One event every msDelay milliseconds /// Timer precision indication (lower value is more precise but resource unfriendly) /// delegate to start /// callBack data  /// one event or multiple events /// Dont forget to call timeKillEvent! /// 0 on failure or any other value as a timer id to use for timeKillEvent [DllImport("winmm.dll", SetLastError = true,EntryPoint="timeSetEvent")] static extern UInt32 timeSetEvent(UInt32 msDelay, UInt32 msResolution, TimerEventHandler handler, ref UInt32 userCtx, UInt32 eventType); ///  /// The multi media timer stop function ///  /// timer id from timeSetEvent /// This function stops the timer [DllImport("winmm.dll", SetLastError = true)] static extern void timeKillEvent( UInt32 uTimerID ); 

Interrompere questi timer dopo averli eseguiti. Sono piuttosto pesanti sul tuo sistema *. Prendi tutte le eccezioni e non lasciare che sfuggano al tuo gestore di eventi.

* Avviare più di 5 timer rallenta seriamente la maggior parte dei sistemi! Esegui il minor numero ansible di codice nei gestori di eventi e assicurati che il codice di esecuzione sia più veloce di 1 millisecondo o faccia fronte a problemi seri. Ho avviato un delegato ogni 10-50 tick per aumentare la visualizzazione dell’etichetta.

Un normale interruttore di thread che si verifica su un Thread.Sleep lascerà uno slot-thread libero dal codice e richiederà circa 40 millisecondi. È anche ansible aumentare la frequenza di cambio thread con alcune chiamate al kernel NT, ma per favore, non farlo.

Innanzitutto, è necessario rendersi conto che è estremamente difficile, se non imansible, eseguire i tempi esatti su un computer a causa delle limitazioni esposte sia dall’hardware che dal software. La buona notizia è che questo tipo di precisione è raramente necessario. Dieci zecche sono una quantità insanamente piccola di tempo. In questo intervallo il lavoro svolto dalla CPU in questo intervallo è molto limitato e non sarà mai statisticamente significativo.

Per riferimento, l’orologio di Windows ha una precisione di circa 10 millisecondi (meno rispetto alle versioni precedenti). Avvolgere il tuo codice con le chiamate a DateTime.UtcNow non andrà meglio di così.

Nella tua domanda, parli di voler “aumentare un evento”. Il problema è che l’unico tipo di object di mantenimento del tempo che solleva un evento a intervalli specifici è l’object Timer . È disponibile in 3 diverse incarnazioni in .NET Framework ( System.Timers.Timer , System.Threading.Timer e System.Windows.Forms.Timer ), ognuno dei quali ha i propri scenari di utilizzo unici e peculiarità relative, ma nessuno dei garantiscono precisione ovunque vicino a ciò che stai chiedendo . Non sono nemmeno progettati per farlo, né esistono funzioni equivalenti esposte dall’API di Windows che forniranno questo tipo di precisione.

La ragione per cui ti ho chiesto perché volevi farlo e se stai cercando di fare un benchmark è perché questo cambia l’intero gioco. .NET Framework (dalla versione 2.0) fornisce un object Stopwatch espressamente progettato per misurare accuratamente il tempo trascorso per una situazione come il benchmarking o il profiling delle prestazioni. Il Stopwatch semplicemente le funzioni dell’API di Windows QueryPerformanceFrequency e QueryPerformanceCounter (che dovrebbe confermare il mio suggerimento sull’uso previsto). Avevamo P / Invocare queste funzioni per accedere a questo tipo di funzionalità nelle versioni precedenti del Framework, ma ora è comodamente integrato. Se hai bisogno di un timer con una risoluzione relativamente alta per il benchmarking, il Stopwatch è la soluzione migliore. In teoria, ti può fornire tempi di sottosecondo.

Ma non è senza i suoi problemi. Non genera alcun evento, quindi se il tuo progetto attuale si basa sulla gestione degli eventi, dovrai ripensarlo. Inoltre, non è garantito che sia perfettamente preciso. Certo, potrebbe avere la risoluzione più alta ansible data i vincoli dell’hardware, ma ciò non significa che soddisferà necessariamente i requisiti dichiarati. Ad esempio, potrebbe non essere affidabile su un sistema con più processori in cui Start e Stop devono essere eseguiti sullo stesso processore. Non dovrebbe avere importanza, ma lo è . È anche sobject ad essere inaffidabile sui processori che possono accelerare la loro velocità di clock su e giù. E oserei dire anche che la chiamata a QueryPerformanceCounter richiederà un po ‘di tempo – circa 5 microsecondi anche su un moderno processore 2+ GHz, che ti impedisce di essere effettivamente in grado di ottenere quella temporizzazione sotto microsecondo che suonava bene in teoria. Poi di nuovo, qualsiasi profiler di codice ragionevole considererebbe trascurabile quella quantità di tempo perché, beh, lo è .
(Vedi anche: http://www.devsource.com/c/a/Techniques/High-Performance-Timing-under-Windows/2/ )

Le varie classi di timer utilizzano una granularità più ampia. Entrambi Threading.Timer e Timers.Timer utilizzano 1/64 di secondo, ovvero 15,66 millisecondi.

Se il “segno di spunta” a cui ci si riferisce è il tick da 100 nanosecondi, utilizzato dalla class DateTime, dalla class TimeSpan e emesso dal cronometro, la lunghezza di 11 tick richiesta è di 1.100 nanosecondi o 1.1 microsecondi. Per quanto ne so, non esiste un timer integrato che ti dia questa risoluzione. Se vuoi davvero che si verifichi un evento ogni 1,1 microsecondi, dovrai rimuovere l’idea di un “timer” e pensare invece in termini di un breve ritardo. Aumenta la priorità di un thread ed esegui il tuo evento in un ciclo. Non chiamare Thread.Sleep (), poiché credo che 1,1 microsecondi siano inferiori al timeslice del programma di pianificazione. Dovrai invece fare un ciclo di ritardo.

Inoltre, renditi conto che l’intervallo di tempo che stai chiedendo è molto, molto piccolo. 1,1 microsecondi sono solo 2.200 cicli di processore su un processore a 2 GHz. Non un importo insignificante, ma non molto tempo per fare molto lavoro. Se stai parlando dell’1 tick che hai detto nel tuo commento, sono solo 200 cicli del processore: è abbastanza tempo per fare alcune decine di operazioni matematiche e forse chiamare una funzione.