System.TimersのTimerクラスの精度は2倍であるため、疑問に思っています(これは、ミリ秒の何分の1かを指定できることを示しているようです)。それは何ですか?
6 に答える
WindowsデスクトップOSは、実際には約40ミリ秒未満では正確ではありません。OSは単にリアルタイムではないため、非決定論的な重大なジッターが発生します。つまり、ミリ秒以下の値を報告する場合もありますが、それらの値が本当に意味のあるものであるとは期待できません。したがって、タイマー間隔がミリ秒未満の値に設定されたとしても、設定から起動までの時間に依存して、実際に希望どおりになることはできません。
この事実に加えて、実行しているフレームワーク全体が非決定的であり(GCが停止し、タイマーが起動する時間帯に収集を行う可能性があります)、最終的には何でもしようとするリスクが発生します。タイムクリティカルです。
System.Timers.Timerは奇妙です。間隔としてdoubleを使用していますが、実際にはMath.Ceilingを呼び出し、その結果をintとしてキャストして、基になるSystem.Threading.Timerで使用します。その場合、理論上の精度は1ミリ秒であり、2,147,483,647ミリ秒を超える間隔を指定することはできません。この情報を考えると、なぜdoubleがintervalパラメーターとして使用されるのか本当にわかりません。
数年前、私はそれが約16msまで正確であることに気づきました...しかし、残念ながら私は詳細を覚えていません。
結果として生じる期間を絶えずサンプリングし、それがどの粒度でステップするかをチェックするループを実行することにより、これを自分で簡単に見つけることができます。
私が比較System.Timers.Timer
したところ、System.Threading.Timer
どちらも8..16ミリ秒前後、特に小さな間隔(1000..6000ミリ秒)で系統的なエラーが発生しました。タイマールーチンの後続の各呼び出しは、最初の呼び出しからの間隔を増やして発生しました。たとえば、2000ミリ秒間隔のタイマーは2000、4012、6024、8036、10048ミリ秒などで起動します(とから取得したタイムスタンプEnvironment.TickCount
はStopwatch.ElapsedTicks
どちらも同じ結果になります)。
タイマーの分解能は、多くの実装作業なしで1msレジームに下がります。この回答double
で精度の理由を説明しました。(マルチメディアタイマーAPIを使用して)1秒あたり1024割り込みで実行するようにシステムを構成する場合、割り込み間の時間は0.9765625ミリ秒です。タイミング問題の標準解像度は100nsです。これらの値は整数として格納されます。値0.9765625は、100nsの分解能で整数の精度を失うことなく保存できません。最後の桁(5)は500psを表します。したがって、解像度は3桁高くする必要があります。これらの時間値を100psの解像度の整数で格納することは、100 psの解像度の8バイト整数が約21350日または約58年後にラップするため、絶望的です。この期間は短すぎて誰にも受け入れられません(Y2Kシナリオを覚えておいてください!)。
詳細については、にリンクされている回答を参照してください。