System.Timers.Timer类执行,准确性测试

时间:2014-01-18 17:57:24

标签: c# timer

我写了这个简单的代码但结果不合理:

public MainWindow()
{
    InitializeComponent();
    write w = new write();
}
public class write{
Timer timer = new Timer(100);

public write()
{
    timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
    timer.Start();
}
StreamWriter str = new StreamWriter("write.txt");
int index = 0;
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
    index++;
    if (index>100)
    {
        timer.Stop();
        str.Close();
        return;
    }
    for (int i = 0; i < 1000; i++)
    {
        //do something
        //run simple commands
    }
    str.WriteLine(DateTime.Now.Millisecond.ToString());
}

结果:

263 365 479 585 697 803 917 24 132 242 348 462 569 675 787 899 6 113 225 331 443 550 664 770 876 988 95 209 315 427 533 647 754 860 972 78 192 299 405 517 629 736 843 955 61 173 280 394 500 606 718 825 939 45 157 263 377 484 590 702 808 922 29 135 247 353 467 574 686 792 904 11 118 230 336 448 555 669 775 887 993 107 214 320 432 538 652 759 865 977 83 197 304 416 522 634 741 848 960 66

为什么它不能被100ms步骤执行?真的是1000次迭代(没有任何命令)并且写入文件大约需要12ms?(参见最后的结果)。

2 个答案:

答案 0 :(得分:1)

Timer类是出了名的不准确

秒表准确无误:

http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx

但不支持调度。如果你想要准确的安排,你必须找到一些不在CLR中的东西,或者自己编写。

答案 1 :(得分:1)

简而言之:您观察到的平均时间是约。 109.15毫秒更多样本可能会收敛到109.375毫秒的平均值。系统时间的粒度可能为15.6250 ms(注意:这可能因硬件/软件平台而异)。系统时间进度的七个步骤累积到109.3750 ms。这几乎告诉您运行15.6250 ms心跳平台。

您可以通过更改系统计时行为来提高准确性。 Windows允许您使用timeBeginPeriod function执行此操作。

修改:更多详情:Obtaining and Setting Timer Resolution

#define TARGET_PERIOD 1         
TIMECAPS tc;
UINT     wTimerRes;

if (timeGetDevCaps(&tc, sizeof(TIMECAPS)) != TIMERR_NOERROR) 
{
    // Error; application can't continue.
}
// Note: tc.wPeriodMin will be 1 for most platforms, however, the following
// line won't allow anything smaller than 1.

wTimerRes = min(max(tc.wPeriodMin, TARGET_PERIOD), tc.wPeriodMax);
// the smallest permitted period is assigned to wTimerRes.

timeBeginPeriod(wTimerRes); 
// most people just say timeBeginPeriod(1); but that's rude
// this call will set the systems interrupt period to the minimum possible.

在较小的中断时段运行会强制更新系统时间在Windows上更频繁地发生&gt; XP SP3(5.1.3)。这减少了系统时间的粒度,从而减小了System.Timers.Timer的粒度。请记住,这可能不适用于使用Windows XP的特定平台。

您可能会获得一毫秒的准确度。但是,无法保证,因为调度可能会在未指定的时间内暂停您的任务。这只能通过增加的进程/线程优先级来克服。有关优先级和修改方法的详细信息,请参阅SetPriorityClass functionSetThreadPriority functionScheduling Priorities