29522


以下のコードを実行すると1秒で処理が終わるはずが10秒ほどかかります。  
CPU8コアのマシンで、他のプログラムはほとんど負荷がなく余裕がある状態です。

何故でしょうか？  
また、意図した通り1ミリ秒だけ待機したいのですがどうしたらいいでしょうか？  
(他のスレッドに処理を移すのでピッタリ1ミリ秒といかないのは理解しています。ですがCPUがほとんど使われていない状態で10倍かかるのは困っています)

[code]

        static void Main(string[] args)
        {
            int n = 0;
            while (true)
            {
    
                Thread.Sleep(1);
                if (n++ > 1000) break;
            }
        }
    
[/code]

補足になりますが、秒間1000回ある処理を行うというのが目的です。  
その処理自体はスレッドで行うのですが、その処理をスレッドに行ってもいいと指令をくだすのがこのメインスレッドです。

補足

回答に提示していただいた下記コードをそのまま実行し、「15000ミリ秒」ほどかかりました。  
Thread.Sleep(1);をコメントアウトすると瞬時で終わります。  
CPUはほとんど使われていません。

[code]

    var stopwatch = Stopwatch.StartNew();
    int n = 0;
    while (true) {
        Thread.Sleep(1);
        if (n++ > 1000) break;
    }
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedMilliseconds);
    
[/code]


CC BY-SA 3.0
2016-10-11T08:27:43.600
29477
2022-06-05T12:56:27.467
2016-10-13T04:56:13.050
14288
14288
question
c# .net
C#でThread.Sleep(1)が明らかに1ミリ秒以上かかっている現象について


1ms sleep × 1000回で10秒かかるとのことですが、何の時間を測定したものでしょうか？

[code]

    var stopwatch = Stopwatch.StartNew();
    int n = 0;
    while (true) {
        Thread.Sleep(1);
        if (n++ > 1000) break;
    }
    stopwatch.Stop();
    Console.WriteLine(stopwatch.ElapsedMilliseconds);
    
[/code]

のように実際の所要時間を測定していないように見受けられます。

プログラムの開始～終了に長時間を要するのであれば、例えばウィルススキャン等の別要因と思われます。

* * *

なお、上記コードでは手元の環境では約1800ミリ秒となりました。これはWindowsの内部クロックが16ミリ秒辺りを基準に動作しているためです。


CC BY-SA 3.0
2016-10-11T09:31:31.327
29479
2016-10-11T09:31:31.327
4236
29477
answer


どうも以下のどちらかの条件でレイテンシが16ms程度に悪化するように思われます。

  * ReleaseビルドのアセンブリをVisual Studio外から起動する
  * Visual Studioホスティングプロセスを有効にしたうえでReleaseビルドのデバッグを行い、しばらく`Thread.Sleep(1)`を実行し続ける (なおVsHub.exeを強制終了すると元に戻ります)

_※実行環境はWindows 10/x64/Visual Studio 2015/32bit優先_

`Release`で発生することから最適化による差異と思われますが、そもそも`Thread.Sleep(int)`の精度は全く保証されておりませんので

  * `Thread.Sleep(1)`の間隔が変化することを見越したプログラムを書く
  * `Thread.Sleep(0)`に変更する（これもレイテンシが変化します）
  * コンテキストスイッチを行わずに1ms待機する

// Thread.Sleep(1)の代わりにwhileで時間を潰す  
while (stopwatch.ElapsedMilliseconds < n + 1){}

というような方針を取った方が良いかと思います。


CC BY-SA 3.0
2016-10-13T07:57:04.060
29522
2016-10-13T07:57:04.060
5750
29477
answer


WindowsのSleepは、1msと指定しても既定では10msほど待ってしまうようです。  
当方のマシンでは、1msだけThread.SleepやTask.Delayで待とうとしましたが、実際には7～15msほど待たれてしまいます。  
以下のような記事が参考になりそうです。  
<http://blog.livedoor.jp/serialpath/archives/37789994.html>  
<http://www.charatsoft.com/develop/otogema/page/02window/sleep.html>


CC BY-SA 4.0
2022-06-05T12:56:27.467
89241
2022-06-05T12:56:27.467
52938
29477
answer