Thread.Sleep verlangsamt restlichen Code

  • C#
  • .NET (FX) 4.5–4.8

Es gibt 2 Antworten in diesem Thema. Der letzte Beitrag () ist von Bluespide.

    Thread.Sleep verlangsamt restlichen Code

    Moin zusammen,

    mir ist schon mal aufgefallen, dass ein Thread.Sleep den rechtlichen Code des Threads verlangsamt. Ich habe da jetzt einmal etwas genauer hingeschaut und einen kleinen Test mit folgendem Code gemacht:

    C#-Quellcode

    1. static void Main(string[] args) {
    2. Stopwatch watch = new Stopwatch();
    3. Random r = new Random();
    4. List<double> timeAverageList = new List<double>(2_000_000);
    5. while (true) {
    6. //Thread.Sleep(50);
    7. double dump = 0.0;
    8. watch.Restart();
    9. for (int i = 0; i < 1_000_000; i++) {
    10. dump += Math.Pow(r.Next(100) * r.Next(100), 3); //Some work
    11. }
    12. watch.Stop();
    13. timeAverageList.Add(watch.Elapsed.TotalMilliseconds);
    14. Console.WriteLine($"{timeAverageList.Average():0.0} {dump}");
    15. }
    16. }


    Bei mir braucht der Code ca. 64ms. Wenn ich jetzt das ​Thread.Sleep(50); einkommentiere, dann braucht der Code ca. 78ms, obwohl das Sleep ja außerhalb der Stopwatch liegt. Ich kann mir das nur so erklären, als das der Scheduler den Thread durch das Sleep als weniger wichtig einstuft und ihm deswegen direkt weniger Zeit zuordnet, auch wenn er gerade was zu tun hat? Bzw. wenn der Thread dauerhaft mehr zu tun hat, ihm dann auch schneller wieder weiter machen lässt?
    Kann man das verhindern, oder hat jemand dazu weitere Infos? Ich finde dazu jetzt nicht wirklich was passendes.
    Mein Problem ist gerade, dass ich eine GameLoop ohne VSync und ohne 100% Kernauslastung auf 60 FPS runter drücken will. Durch genanntes Problem braucht er aber dann für die Schleife an sich deutlich länger und es tauchen höhere Peeks an Unterbrechungen auf.
    @Bluespide Interessant.
    Teste das mal mit Sleep(0), da wird auf den Beginn der nächsten Zeitscheibe gewartet.
    Lässt sich bei Deinem Hauptproblem was mit Parallelisierung machen (Parallel.For(), Parallel.ForEach())?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Moin Rod,

    mit Sleep(0) messe ich keine Verlangsamung des Codes, aber dafür läuft dann auch der Kern auf 100%. Er gibt also intern irgendwie ab, aber nicht wirklich. Ich habe auch schon ein bisschen mit ​Thread.Yield(), ​Thread.SpinWait() und der ​SpinWait Struktur rum gespielt. Ich habe auch ein bisschen in das Framework bei den Concurrent- Klassen geschaut, die sind ja auch teilweise extra ohne lock aufgebaut und benutzten zum warten eben genau dieses Abgeben der verbleibenden Zeitscheiben. Leider bleibt dabei die Prozessorauslastung immer hoch. Ich wollte halt eigentlich die CPU etwas "schonen", wenn ich genau weiß, dass ich jetzt länger warten muss. Aber nicht zum Preis, dass der restliche Code dann länger dauert.

    Zu dem Hauptproblem. Ja ich habe da schon teilweise Parallelisierung drin, nur das Rendern mit OpenGL ist leider kaum Parallel möglich. Das haben die soweit ich weiß jetzt erst mit Vulkan bzw. DirectX 12 so richtig angefangen in die Grafikkarten zu bringen.