Thread.Sleep(TimeSpan) の精度はどのくらいですか? 質問する

Thread.Sleep(TimeSpan) の精度はどのくらいですか? 質問する

経過時間が予想と異なるため、断続的に失敗するユニット テストに遭遇しました。

このテストの例は次のようになります。

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

TimeSpan oneSecond = new TimeSpan(0, 0, 1);

for(int i=0; i<3; i++)
{
    Thread.Sleep(oneSecond);
}

stopwatch.Stop();

Assert.GreaterOrEqual(stopwatch.ElapsedMilliseconds, 2999);

ほとんどの場合、これは成功しますが、少なくとも 1 回は失敗しました。その理由は次のとおりです。

予想: 2999 以上 しかし実際は: 2998

どうして 3 秒未満になるのか理解できません。私が知らないうちに、Thread.Sleep または Stopwatch に精度の問題があるのでしょうか?

以下の質問のいくつかを更新します。ユニット テストされているシナリオは、メソッドを呼び出して何らかのアクションを実行し、失敗した場合は少し待ってからそのメソッドを思い出すことができるクラスです。上記のテストは、実際に起こっていることの近似値にすぎません。

たとえば、DoSomething() メソッドを呼び出したいが、DoSomething() によって例外がスローされた場合、最大 3 回まで呼び出しを再試行し、各試行の間に 1 秒待機できるようにしたいとします。この場合の単体テストの目的は、各再試行の間に 1 秒待機して 3 回の再試行を要求したときに、かかった合計時間が 3 秒を超えることを確認することです。

ベストアンサー1

あなたのスレッドは他のスレッドと CPU 時間を共有しています。あなたの番が再び来るとすぐにスリープは終了し、カーネルはスリープ時間が経過したことを認識するので、それほど正確ではありません。

CPU 負荷、プロセスの優先度、同時スレッド数、さらには他のプロセスからのスレッド数も、これに影響を与えます。

おすすめ記事