Comment puis-je faire dormir mon programme C # pendant 50 millisecondes?
Cela peut sembler une question facile, mais j'ai un moment d'insuffisance cérébrale temporaire!
System.Threading.Thread.Sleep(50);
Rappelez-vous cependant que faire cela dans le fil principal de l'interface graphique empêchera votre interface graphique de se mettre à jour (cela vous semblera "lent")
Supprimez simplement le ;
pour le faire fonctionner également sur VB.net.
Il y a fondamentalement 3 choix pour attendre dans (presque) n'importe quel langage de programmation:
pour 1. - Attente lâche en C #:
Thread.Sleep(numberOfMilliseconds);
Cependant, le planificateur de threads Windows fait en sorte que la précision de Sleep()
soit d'environ 15 ms (le mode veille peut donc facilement attendre 20 ms, même s'il est programmé d'attendre juste 1 ms).
pour 2. - Attente serrée en C # est:
Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
//some other processing to do possible
if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
{
break;
}
}
Nous pourrions aussi utiliser DateTime.Now
ou d'autres moyens de mesure du temps, mais Stopwatch
est beaucoup plus rapide (et cela deviendrait vraiment visible en boucle serrée).
pour 3. - Combinaison:
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
}
Ce code bloque régulièrement le thread pendant 1 ms (ou un peu plus, en fonction de la planification des threads du système d'exploitation), de sorte que le processeur n'est pas occupé pendant cette période de blocage et que le code ne consomme pas 100% de sa puissance. D'autres traitements peuvent toujours être effectués entre les blocages (tels que: la mise à jour de l'interface utilisateur, la gestion des événements ou la réalisation d'interactions/communications).
Vous ne pouvez pas spécifier un temps de repos exact dans Windows. Vous avez besoin d'un système d'exploitation en temps réel pour cela. Le mieux que vous puissiez faire est de spécifier un temps de repos minimum . Ensuite, il appartient au planificateur de réactiver votre thread après cela. Et jamais appelez .Sleep()
sur le fil de l'interface graphique.
Depuis que vous avez la fonctionnalité async/wait, le meilleur moyen de dormir pendant 50 ms consiste à utiliser Task.Delay:
async void foo()
{
// something
await Task.Delay(50);
}
Ou si vous visez .NET 4 (avec Async CTP 3 pour VS2010 ou Microsoft.Bcl.Async), vous devez utiliser:
async void foo()
{
// something
await TaskEx.Delay(50);
}
De cette façon, vous ne bloquerez pas le fil de l'interface utilisateur.
Utilisez ce code
using System.Threading;
// ...
Thread.Sleep(50);
Thread.Sleep(50);
L'exécution du thread ne sera pas planifiée par le système d'exploitation pendant la durée spécifiée. Cette méthode modifie l'état du thread pour inclure WaitSleepJoin.
Cette méthode n'effectue pas de pompage COM et SendMessage standard. Si vous devez dormir sur un thread comportant STAThreadAttribute, mais que vous souhaitez effectuer un pompage COM et SendMessage standard, envisagez d'utiliser l'une des surcharges de la méthode Join qui spécifie un intervalle de délai d'attente.
Thread.Join
Thread.Sleep
Pour la lisibilité:
using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
À partir de .NET Framework 4.5, vous pouvez utiliser:
using System.Threading.Tasks;
Task.Delay(50).Wait(); // wait 50ms
Le meilleur des deux mondes:
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);
}