不思議なことに、あなたのコードはWin7のクアッドコアで完全に正常に機能し、ほぼ毎回正確に2ミリ秒離れた値を生成します。
だから私はもっと徹底的なテストをしました。これが私の出力例ですThread.Sleep(1)
。DateTime.UtcNow
このコードは、ループ内の連続する呼び出し間のミリ秒数を出力します。

各行には100文字が含まれているため、「クリーンラン」での100ミリ秒の時間を表します。したがって、この画面は約2秒をカバーします。最長のプリエンプションは4msでした。さらに、すべての反復が正確に1ミリ秒かかったときに、約1秒続く期間がありました。これはほぼリアルタイムのOS品質です。1 :)
だから私は今回、もう一度試しましThread.Sleep(2)
た:

繰り返しますが、ほぼ完璧な結果です。今回は各行の長さが200ミリ秒で、ほぼ3秒の長さの実行があり、ギャップは正確に2ミリ秒以外にはなりませんでした。
当然、次に確認するのは、DateTime.UtcNow
私のマシンの実際の解像度です。これは、まったく眠っていない実行です。まったく変更されていない.
場合はaが出力されます:UtcNow

最後に、上記の結果を生成した同じマシン上でタイムスタンプが15ミリ秒離れているという奇妙なケースを調査しているときに、次の奇妙な出来事に遭遇しました。

Windows APIにはtimeBeginPeriod
、アプリケーションがタイマーの頻度を一時的に上げるために使用できるという関数があります。したがって、これがおそらくここで起こったことです。タイマー解像度の詳細なドキュメントは、 Hardware Dev Center Archive、特にTimer-Resolution.docx(Wordファイル)から入手できます。
結論:
DateTime.UtcNow
15msよりもはるかに高い解像度を持つことができます
Thread.Sleep(1)
正確に1ms眠ることができます
- 私のマシンでは、
UtcNow
成長は一度に正確に1msずつ成長します(丸め誤差を与えるか取る-Reflectorはに除算があることを示していますUtcNow
)。
- すべてが15.6msベースの場合、プロセスを低解像度モードに切り替えることができ、1msスライスの高解像度モードにオンザフライで切り替えることができます。
コードは次のとおりです。
static void Main(string[] args)
{
Console.BufferWidth = Console.WindowWidth = 100;
Console.WindowHeight = 20;
long lastticks = 0;
while (true)
{
long diff = DateTime.UtcNow.Ticks - lastticks;
if (diff == 0)
Console.Write(".");
else
switch (diff)
{
case 10000: case 10001: case 10002: Console.ForegroundColor=ConsoleColor.Red; Console.Write("1"); break;
case 20000: case 20001: case 20002: Console.ForegroundColor=ConsoleColor.Green; Console.Write("2"); break;
case 30000: case 30001: case 30002: Console.ForegroundColor=ConsoleColor.Yellow; Console.Write("3"); break;
default: Console.Write("[{0:0.###}]", diff / 10000.0); break;
}
Console.ForegroundColor = ConsoleColor.Gray;
lastticks += diff;
}
}
タイマーの解像度を変更する可能性のある文書化されていない関数が存在することが判明しました。詳細は調べていませんが、ここにリンクを貼ろうと思いましたNtSetTimerResolution
。
1もちろん、OSが可能な限りアイドル状態であり、4つのかなり強力なCPUコアを自由に使用できることを確認しました。4つのコアすべてを100%にロードすると、画像が完全に変化し、どこでも長いプリエンプションが発生します。