web-dev-qa-db-fra.com

Comment puis-je mettre mon programme C # en veille pendant 50 ms?

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!

263
TK.
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.

315
Isak Savo

Il y a fondamentalement 3 choix pour attendre dans (presque) n'importe quel langage de programmation:

  1. Attente lâche
    • Exécution de blocs de threads pour une durée donnée (= ne consomme pas de puissance de traitement)
    • Aucun traitement n'est possible sur le thread bloqué/en attente
    • Pas si précis
  2. attente serrée (aussi appelée boucle serrée)
    • le processeur est TRÈS occupé pendant tout l'intervalle d'attente (en fait, il consomme généralement 100% du temps de traitement d'un cœur)
    • Certaines actions peuvent être effectuées en attente
    • Tres précis
  3. Combinaison des 2 précédents
    • Il combine généralement l'efficacité de traitement de 1. et la précision + la capacité de faire quelque chose de 2.

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).

147
Thetam

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.

54
Joel Coehoorn

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.

44
Toni Petrina

Utilisez ce code

using System.Threading;
// ...
Thread.Sleep(50);
31
Alexander Prokofyev
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
14
SelvirK
Thread.Sleep
10
Roger Lipscombe

Pour la lisibilité:

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
3
Colonel Panic

À partir de .NET Framework 4.5, vous pouvez utiliser:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms
0
timmebee

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);
    }
0
Akumaburn