两者都以System.Timers.Timer
与System.Threading.Timer
请求的间隔相当大的间隔发射。例如:
new System.Timers.Timer(1000d / 20);
产生一个每秒触发 16 次的计时器,而不是 20 次。
为了确保没有太长的事件处理程序的副作用,我编写了这个小测试程序:
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 赫兹;实际: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 赫兹
实际频率与请求频率的偏差高达 36%。(而且显然不能超过 64 Hz。)鉴于微软推荐这个计时器是因为它的“更高的准确性” System.Windows.Forms.Timer
,这让我感到困惑。
顺便说一句,这些不是随机偏差。它们每次都是相同的值。另一个计时器类的类似测试程序System.Threading.Timer
显示了完全相同的结果。
在我的实际程序中,我需要每秒精确地收集 50 个样本的测量值。这还不需要实时系统。每秒获得 32 个样本而不是 50 个样本是非常令人沮丧的。
有任何想法吗?
@Chris:你是对的,间隔似乎都是 1/64 秒左右的整数倍。顺便说一句,在事件处理程序中添加 Thread.Sleep(...) 没有任何区别。考虑到使用线程池,这是有道理System.Threading.Timer
的,因此每个事件都在空闲线程上触发。