C#でThread.Sleep(1)が明らかに1ミリ秒以上かかっている現象について


以下のコードを実行すると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]




どうも以下のどちらかの条件でレイテンシが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){}

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




どうも以下のどちらかの条件でレイテンシが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){}

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

