2008-09-18 3 views
236

Wie bekomme ich mein C# -Programm für 50 Millisekunden schlafen?Wie bekomme ich mein C# -Programm für 50 ms in den Ruhezustand?

Dies scheint eine einfache Frage zu sein, aber ich habe einen vorübergehenden Hirnversagen Moment!

+1

Re-getaggt VB.NET als die Antwort auch dort funktioniert. –

+0

Nein DrFloyd5,; funktioniert nicht auf VB.NET, oder? – Zanoni

+14

Wenn ich im VB.Net-Team wäre, würde ich hinzufügen; als Kommentarzeichen zur nächsten Version der Sprache ... –

Antwort

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

Denken Sie jedoch daran, dass dieser Thread in der Haupt GUI tun, um Ihre GUI von der Aktualisierung blockiert (es fühlt „träge“)

einfach die ; entfernen, um es für VB zu arbeiten. auch netto.

+0

Wird nach dem Aufruf von sleep in einer Methode das Programm weiterhin im Hintergrund ausgeführt (ohne einen neuen Thread zu erstellen)? Wenn ich den Schlaf in einem neuen Thread anrufe, wird der Haupt-Thread seine Arbeit fortsetzen? –

+0

@JayNirgudkar Der Thread, der den Schlaf aufruft, wird gestoppt. Andere Threads sind nicht betroffen. –

+0

Dies ist nicht garantiert, um genau zu sein. – Akumaburn

10
Thread.Sleep 
31

dieser Code verwenden

using System.Threading; 
// ... 
Thread.Sleep(50); 
14
Thread.Sleep(50); 

Der Faden wird nicht zur Ausführung durch das Betriebssystem für die Zeitdauer angegeben geplant werden. Diese Methode ändert den Status des Threads, um WaitSleepJoin einzuschließen.

Diese Methode führt kein Standard-COM- und SendMessage-Pumpen durch. Wenn Sie in einem Thread schlafen müssen, der STAThreadAttribute enthält, aber das Standard-COM- und SendMessage-Pumpen durchführen möchten, sollten Sie eine der Überladungen der Join-Methode verwenden, die ein Zeitüberschreitungsintervall angibt.

Thread.Join 
54

können Sie keine genaue Schlafzeit in Windows angeben. Sie benötigen dafür ein Echtzeit-Betriebssystem. Das Beste, was Sie tun können, ist eine Minimum Schlafzeit angeben. Dann ist es Aufgabe des Schedulers, den Thread danach wieder aufzuwecken. Und nie Anruf .Sleep() auf dem GUI-Thread.

139

Grundsätzlich gibt es drei Möglichkeiten für in (fast) jeder Programmiersprache warten:

  1. Lose warten
    • für bestimmte Zeit ausgeführten Thread-Blöcke (= nicht verbrauchen Rechenleistung)
    • Keine Bearbeitung ist bei gesperrtem/wartendem Thread möglich
    • Nicht so genau
  2. feste Warte (auch enge Schleife genannt)
    • Prozessor ist sehr beschäftigt für das gesamte Warteintervall (in der Tat, es verbraucht in der Regel 100% einer Verarbeitungszeit des Kerns)
    • Einige Aktionen durchgeführt werden können, während der Wartezeit
    • Sehr präzise
  3. Kombination früherer 2
    • Es kombiniert in der Regel Verarbeitungseffizienz von 1. und Genauigkeit + Fähigkeit, etwas von 2 zu tun.

für 1. - Lockere Warte in C#:

Thread.Sleep(numberOfMilliseconds); 

jedoch Fenster Thread-Scheduler acccuracy von Sleep() verursacht um 15 ms zu sein (so kann Schlaf leicht warten 20ms, auch wenn geplant ist, nur für 1ms zu warten).

für 2. - Enge Warte in C# ist:

Stopwatch stopwatch = Stopwatch.StartNew(); 
while (true) 
{ 
    //some other processing to do possible 
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait) 
    { 
     break; 
    } 
} 

Wir auch DateTime.Now oder andere Mittel zur Zeitmessung verwenden könnten, aber Stopwatch ist viel schneller (und das wäre wirklich sichtbar wird in enger Schleife).

für 3. - Kombination:

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 
} 

Dieser Code regelmäßig Gewindesätze für 1 ms (oder etwas mehr, abhängig von Thread-Scheduling O), so Prozessor nicht ausgelastet ist für diese Zeit der Sperrung und Code verbraucht nicht 100% der Prozessorleistung. Eine andere Verarbeitung kann immer noch zwischen dem Blockieren durchgeführt werden (wie zum Beispiel: Aktualisieren der UI, Behandeln von Ereignissen oder Durchführen von Interaktions-/Kommunikationsmaterial).

+1

[Timer] (https://msdn.microsoft.com/en-us/library/system.timers.timer%28v=vs.110%29.aspx) kann auch von Interesse sein –

38

Seit jetzt haben Sie async/await Funktion, der beste Weg für 50ms schlafen ist von Task.Delay mit:

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

Oder wenn Sie zielen .NET 4 (mit Async CTP 3 für VS2010 oder Microsoft.Bcl.Async), müssen Sie verwenden:

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

Auf diese Weise werden Sie nicht UI-Thread blockieren.

+0

können Sie response.flush während dieses Vorgangs Verzögerung, wenn es in einer Schleife ist? –

+0

Nein, das geht nicht. Ich glaube, es gibt eine 'FlushAsync'-Version. –

+4

Eine Alternative, die keine 'async'-Deklaration erfordert, ist' Task.Delay (50) .Wait(); 'aufzurufen – stuartd

3

Zur besseren Lesbarkeit:

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

Beste aus beiden Welten:

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); 
    } 
Verwandte Themen