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


272

Comment mettre mon programme C # en veille pendant 50 millisecondes?

Cela peut sembler une question facile, mais j'ai un moment d'insuffisance cérébrale temporaire!


1
Re-tagué vers VB.NET car la réponse y fonctionne également.
DrFloyd5

Pas de DrFloyd5,; ne fonctionne pas sur VB.NET, non?
Zanoni

16
Si j'étais dans l'équipe VB.Net, j'ajouterais; comme un personnage de commentaire à la prochaine version de la langue ...
Joel Coehoorn

4
Je pense que les programmeurs VB sont assez brillants pour trouver l'équivalent ..
BlueRaja - Danny Pflughoeft

bien, juste pour être sûr, maintenant ils n'ont plus à le faire.
PsychoData

Réponses:


330
System.Threading.Thread.Sleep(50);

Rappelez-vous cependant que le faire dans le thread principal de l'interface graphique empêchera votre interface graphique de se mettre à jour (cela semblera "lent")

Supprimez simplement le ;pour le faire fonctionner également pour VB.net.


Après avoir appelé sleep dans une méthode, le programme continuera-t-il à s'exécuter en arrière-plan (sans créer de nouveau thread)? De plus, si j'appelle sleep dans un nouveau thread, le thread principal continuera-t-il son travail?
Jay Nirgudkar

@JayNirgudkar le thread qui appelle Sleep sera arrêté. Les autres threads ne sont pas affectés.
Isak Savo

Ce n'est pas garanti d'être exact.
Akumaburn

150

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

  1. Attente lâche
    • Exécution de blocs de threads pour un temps donné (= 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 (également 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 attendant
    • Tres précis
  3. Combinaison des 2 précédents
    • Il combine généralement une efficacité de traitement de 1 et une précision + une capacité de faire quelque chose de 2.

pour 1. - Attente lâche en C #:

Thread.Sleep(numberOfMilliseconds);

Cependant, le planificateur de threads Windows entraîne une précision d' Sleep()environ 15 ms (donc Sleep peut facilement attendre 20 ms, même s'il est prévu d'attendre juste 1 ms).

pour 2. - Une 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 également utiliser DateTime.Nowou d'autres moyens de mesure du temps, mais Stopwatchc'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 légèrement plus, selon la planification du thread du système d'exploitation), donc le processeur n'est pas occupé pendant cette période de blocage et le code ne consomme pas 100% de la puissance du processeur. D'autres traitements peuvent toujours être effectués entre les blocages (tels que: mise à jour de l'interface utilisateur, gestion des événements ou faire des choses d'interaction / communication).


1
La minuterie peut également être intéressante
JonnyRaa

55

Vous ne pouvez pas spécifier une heure de veille exacte 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 sommeil minimum . Ensuite, c'est au planificateur de réveiller votre thread après cela. Et ne faites jamais appel .Sleep()au thread GUI.


44

Depuis que vous avez une fonction asynchrone / attente, la meilleure façon de dormir pendant 50 ms est d'utiliser Task.Delay:

async void foo()
{
    // something
    await Task.Delay(50);
}

Ou si vous ciblez .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 thread d'interface utilisateur.


pouvez-vous response.flush pendant ce délai, s'il est dans une boucle?
Teoman shipahi

Non tu ne peux pas. Je crois qu'il existe une FlushAsyncversion.
Toni Petrina du

6
Une alternative qui ne nécessite pas de asyncdéclaration est d'appelerTask.Delay(50).Wait();
stuartd


14
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 qui a 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'expiration.

Thread.Join

5

Pour plus de lisibilité:

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

0

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

using System.Threading.Tasks;

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

-1

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);
    }
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.