Come faccio a far dormire il mio programma C # per 50 millisecondi?
Questa potrebbe sembrare una domanda facile, ma sto avendo un momento temporaneo di insuccesso cerebrale!
System.Threading.Thread.Sleep(50);
Ricorda però che fare questo nel thread della GUI principale bloccherà la tua GUI dall'aggiornamento (sembrerà "pigra")
Basta rimuovere ;
per farlo funzionare anche per VB.net.
Ci sono fondamentalmente 3 scelte per aspettare (quasi) qualsiasi linguaggio di programmazione:
per 1. - In attesa in C #:
Thread.Sleep(numberOfMilliseconds);
Tuttavia, l'utilità di pianificazione dei thread di Windows fa sì che l'accuratezza di Sleep()
sia di circa 15 ms (quindi Sleep può facilmente attendere 20 ms, anche se pianificato per attendere solo 1 ms).
per 2. - Stretta attesa in C # è:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do possible
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
}
Potremmo anche usare DateTime.Now
o altri mezzi di misurazione del tempo, ma Stopwatch
è molto più veloce (e questo diventerebbe davvero visibile in un loop ristretto).
per 3. - Combinazione:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do STILL POSSIBLE
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
Thread.Sleep(1); //so processor can rest for a while
}
Questo codice blocca regolarmente il thread per 1 ms (o leggermente di più, in base alla pianificazione dei thread del sistema operativo), quindi il processore non è occupato per il tempo di blocco e il codice non consuma il 100% della potenza del processore. È comunque possibile eseguire altre elaborazioni tra un blocco e l'altro (ad esempio: aggiornamento dell'interfaccia utente, gestione di eventi o attività di interazione/comunicazione).
Non è possibile specificare un esatto tempo di sospensione in Windows. Hai bisogno di un sistema operativo in tempo reale per questo. Il meglio che puoi fare è specificare un minimo tempo di sonno. Quindi spetta al programmatore di riattivare il thread dopo. E never chiama .Sleep()
sul thread della GUI.
Poiché ora disponi di funzionalità asincrone/attese, il modo migliore per dormire per 50 ms è utilizzare Task.Delay:
async void foo()
{
// something
await Task.Delay(50);
}
O se si utilizza .NET 4 (con Async CTP 3 per VS2010 o Microsoft.Bcl.Async), è necessario utilizzare:
async void foo()
{
// something
await TaskEx.Delay(50);
}
In questo modo non bloccherai il thread dell'interfaccia utente.
Usa questo codice
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
Il thread non verrà pianificato per l'esecuzione dal sistema operativo per la quantità di tempo specificato. Questo metodo cambia lo stato del thread per includere WaitSleepJoin.
Questo metodo non esegue il pompaggio COM e SendMessage standard. Se è necessario dormire su un thread che dispone di STAThreadAttribute, ma si desidera eseguire il pompaggio standard COM e SendMessage, considerare l'utilizzo di uno degli overload del metodo Join che specifica un intervallo di timeout.
Thread.Join
Thread.Sleep
Per leggibilità:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
Il meglio di entrambi i mondi:
using System.Runtime.InteropServices;
[DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
private static extern uint TimeBeginPeriod(uint uMilliseconds);
[DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
private static extern uint TimeEndPeriod(uint uMilliseconds);
/**
* Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
*/
private void accurateSleep(int milliseconds)
{
//Increase timer resolution from 20 miliseconds to 1 milisecond
TimeBeginPeriod(1);
Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
stopwatch.Start();
while (stopwatch.ElapsedMilliseconds < milliseconds)
{
//So we don't burn cpu cycles
if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
{
Thread.Sleep(5);
}
else
{
Thread.Sleep(1);
}
}
stopwatch.Stop();
//Set it back to normal.
TimeEndPeriod(1);
}