両方とも、要求されたものとはかなり異なる間隔で発砲しますSystem.Timers.Timer
。System.Threading.Timer
例えば:
new System.Timers.Timer(1000d / 20);
1 秒あたり 20 回ではなく、16 回起動するタイマーが生成されます。
長すぎるイベント ハンドラーによる副作用がないことを確認するために、次の小さなテスト プログラムを作成しました。
int[] frequencies = { 5, 10, 15, 20, 30, 50, 75, 100, 200, 500 };
// Test System.Timers.Timer
foreach (int frequency in frequencies)
{
int count = 0;
// Initialize timer
System.Timers.Timer timer = new System.Timers.Timer(1000d / frequency);
timer.Elapsed += delegate { Interlocked.Increment(ref count); };
// Count for 10 seconds
DateTime start = DateTime.Now;
timer.Enabled = true;
while (DateTime.Now < start + TimeSpan.FromSeconds(10))
Thread.Sleep(10);
timer.Enabled = false;
// Calculate actual frequency
Console.WriteLine(
"Requested frequency: {0}\nActual frequency: {1}\n",
frequency, count / 10d);
}
出力は次のようになります。
要求: 5 Hz; 実際: 4,8 Hz
要求: 10 Hz; 実際: 9,1 Hz
要求: 15 Hz; 実際: 12,7 Hz
要求: 20 Hz; 実際: 16 Hz
要求: 30 Hz; 実際: 21,3 Hz
要求: 50 Hz; 実際: 31,8 Hz
要求: 75 Hz; 実際: 63,9 Hz
要求: 100 Hz; 実際: 63,8 Hz
要求: 200 Hz; 実際: 63,9 Hz
要求: 500 Hz; 実際: 63,9 Hz
実際の周波数は、要求された周波数から最大 36% ずれています。(そして明らかに 64 Hz を超えることはできません。) Microsoft が よりも「精度が高い」ためにこのタイマーを推奨していることを考えるとSystem.Windows.Forms.Timer
、これは私を困惑させます。
ところで、これらはランダムな偏差ではありません。それらは毎回同じ値です。また、他のタイマー クラス の同様のテスト プログラムSystem.Threading.Timer
は、まったく同じ結果を示します。
私の実際のプログラムでは、1 秒あたり正確に 50 サンプルで測定値を収集する必要があります。これにはまだリアルタイム システムは必要ありません。また、1 秒あたり 50 サンプルではなく 32 サンプルを取得するのは非常にイライラします。
何か案は?
@クリス:そうです、間隔はすべて1/64秒前後の整数倍のようです。ところで、イベント ハンドラに Thread.Sleep(...) を追加しても違いはありません。がスレッド プールを使用することを考えると、これは理にかなってSystem.Threading.Timer
います。そのため、各イベントはフリー スレッドで発生します。