Thread. Dormire per meno di 1 millisecondo

Voglio chiamare il thread sleep con meno di 1 millisecondo. Ho letto che né thread. Sleep né Windows-OS lo supportano.

qual è la soluzione per questo?

Per tutti quelli che si chiedono perché ho bisogno di questo: sto facendo uno stress test e voglio sapere quanti messaggi il mio modulo può gestire al secondo. Quindi il mio codice è:

// Set the relative part of Second hat will be allocated for each message //For example: 5 messages - every message will get 200 miliseconds var quantum = 1000 / numOfMessages; for (var i = 0; i < numOfMessages; i++) { _bus.Publish(new MyMessage()); if (rate != 0) Thread.Sleep(quantum); } 

Sarò felice di avere la tua opinione su questo.

Non puoi farlo. Una singola chiamata di sonno in genere blocca più a lungo di un millisecondo (dipende dal sistema operativo e dal sistema, ma nella mia esperienza, Thread.Sleep(1) tende a bloccarsi da qualche parte tra 12-15 ms).

Windows, in generale, non è progettato come un sistema operativo in tempo reale . Questo tipo di controllo è in genere imansible da ottenere nelle versioni normali (desktop / server) di Windows.

Il più vicino che si può ottenere è tipicamente girare e mangiare i cicli della CPU fino a quando non si è raggiunto il tempo di attesa desiderato (misurato con un contatore ad alte prestazioni). Questo, comunque, è piuttosto orribile: mangerete un’intera CPU, e anche in quel caso, probabilmente vi verrà anticipato dal sistema operativo a volte ed effettivamente “dormirete” per più di 1ms …

Il codice seguente offrirà sicuramente un modo più preciso di bloccare, piuttosto che chiamare Thread.Sleep(x); (sebbene questo metodo bloccherà il thread, non lo metterà in stop ). Qui sotto stiamo usando la class StopWatch per misurare per quanto tempo dobbiamo mantenere il loop e bloccare il thread chiamante.

 using System.Diagnostics; private static void NOP(double durationSeconds) { var durationTicks = Math.Round(durationSeconds * Stopwatch.Frequency); var sw = Stopwatch.StartNew(); while (sw.ElapsedTicks < durationTicks) { } } 

Esempio di utilizzo,

 private static void Main() { NOP(5); // Wait 5 seconds. Console.WriteLine("Hello World!"); Console.ReadLine(); } 

Perché?
Di solito c’è un numero molto limitato di CPU e core su una macchina – si ottiene solo un piccolo numero di unità di esecuzione indipendenti.

Dall’altra parte ci sono un numero di processi e molti altri thread. Ogni thread richiede un po ‘di tempo per il processore, che viene assegnato internamente dai processi core di Windows. Solitamente Windows blocca tutti i thread e fornisce una certa quantità di tempo core della CPU a thread specifici, quindi cambia il contesto in altri thread.

Quando chiami Thread.Sleep, non importa quanto tu possa uccidere per tutto il tempo che Windows ha dedicato alla discussione, poiché non c’è ragione di aspettarlo e il contesto viene cambiato immediatamente. Potrebbero essere necessari alcuni ms quando Windows fornirà al thread un po ‘di CPU la volta successiva.

Cosa usare?
In alternativa, puoi girare la tua CPU , girare non è una cosa terribile da fare e può essere molto utile. Ad esempio, viene utilizzato molto nello spazio dei nomi System.Collections.Concurrent con raccolte non bloccanti, ad esempio:

 SpinWait sw = new SpinWait(); sw.SpinOnce(); 

La maggior parte dei motivi Thread.Sleep(1) per l’utilizzo di Thread.Sleep(1) o Thread.Sleep(0) riguarda tecniche di sincronizzazione dei thread abbastanza avanzate. Come ha detto Reed , non otterrai la risoluzione desiderata usando le tecniche convenzionali. Non so per certo cosa stia cercando di realizzare, ma penso di poter supporre che tu voglia fare un’azione a intervalli di 1 millisecondo. Se è così, dai un’occhiata ai timer multimediali . Possono fornire una risoluzione fino a 1 ms. Sfortunatamente, non ci sono API integrate in .NET Framework (di cui sono a conoscenza) che tocchi questa funzionalità di Windows. Ma puoi usare il livello di interoperabilità per chiamare direttamente nelle API Win32. Ci sono anche esempi di come farlo in C # là fuori.

Ai vecchi tempi, si utilizzava l’API “QueryPerformanceTimer” di Win32, quando era necessaria una risoluzione inferiore al millisecondo.

Sembra che ci siano più informazioni sull’argomento su Code-Project: http://www.codeproject.com/KB/cs/highperformancetimercshar.aspx

Questo non ti permetterà di “Dormire ()” con la stessa risoluzione indicata da Reed Copsey.

Modifica: come sottolineato da Reed Copsey e Brian Gideon, QueryPerfomanceTimer è stato sostituito da Stopwatch in .NET.