.Net中的计时器和循环是否准确?

Far*_*man 2 .net c# loops timer

在开发一个程序来计算由555定时器IC产生的脉冲的频率和脉冲宽度时,通过PC并行端口进入PC.我注意到每次运行代码时它都显示不同的值,所以我开始测试循环和定时器的准确性.我运行了以下代码,并指出它们不准确(我可能错了,请纠正我,如果我是!):

对于计时器:

    int sec = 0;
    private void button2_Click(object sender, EventArgs e)
    {
        sec = DateTime.Now.Second;
        i = 0;
        timer1.Enabled = true;
    }

    private void timer1_Tick(object sender, EventArgs e)
    {
        if (sec == DateTime.Now.Second)
        {
            i++;
        }
        else
        {
            timer1.Enabled = false;
            MessageBox.Show(i.ToString(),"Timer Output");
        }
    }
Run Code Online (Sandbox Code Playgroud)

输出: 应该相同,但是:

在此输入图像描述 在此输入图像描述 在此输入图像描述

对于LOOP:

    private void button1_Click(object sender, EventArgs e)
    {
        i = 0;
        CheckForIllegalCrossThreadCalls = false;
        Thread t1 = new Thread(LoopTest);
        t1.Start();
    }

    void LoopTest()
    {
        System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        sw.Start();
        this.Cursor = Cursors.WaitCursor;
        while (true)
        {
            if (sw.ElapsedMilliseconds != 1000)
            {
                i++;
            }
            else
            {
                break;
            }
        }
        sw.Stop();
        this.Cursor = Cursors.Default;
        MessageBox.Show(i.ToString(), "Loop Output");
    }
Run Code Online (Sandbox Code Playgroud)

输出: 应该相同,但是:

在此输入图像描述 在此输入图像描述 在此输入图像描述

我该怎么做才能使循环和计时器准确,有什么办法吗?或者我必须去硬和复杂的C代码和DOS?

我认为这是在这个问题中给我错误的值的基本原因:计数并行端口输入频率 - C#

Ed *_* S. 16

1)请勿DateTime.Now用于性能测量,请使用StopWatch.

2)" OUTPUT: Should be same, but .."

为什么他们呢?您正在非RTOS(实时操作系统)上运行托管/ JIT代码.如果操作系统感觉像你那么代码可以随时被反弹.是什么让你相信在这种环境中运行相同的代码N次应该总是产生相同的结果到如此小的程度?

3)Windows上的定时器分辨率约为15ms.对于非常准确的时序,最好的选择是支持它的系统(CPU)上的HighPerformanceTimer API.你甚至没有向我们展示计时器的间隔.

你在这里没有考虑很多变量而你的预测基于错误的假设.你甚至测量过这段代码多少次?你是否考虑过第一次编译它所需的时间?你在发布模式下运行吗?通过VS?是否有许多任务在后台运行?我可以继续

  • @ Farid-ur-Rahman:我想你错过了我的观点.定义"完全准确性".你的假设是不正确的.您希望代码在每次运行时花费几乎完全相同的时间,但您在Windows上运行(非RTOS,甚至不是软实时)并调用必须在第一次传递时编译的托管代码.通过VS运行也与正常运行不同.您需要进行测试以确保代码(尽管如此)*满足您的要求*,而不是一些错误的假设,即它应该总是花费N ms来调用计时器...... (2认同)

Arn*_*rno 12

仔细实施允许在大多数Windows平台上测量时间段,精确度仅为几微秒.请注意以下事实:

  1. Windows不是实时操作系统:这在这里无关紧要!

  2. 利用进程/线程优先级:SetPriorityClass最高可达REALTIME_PRIORITY_CLASS,SetThreadPriority最高可达THREAD_PRIORITY_TIME_CRITICAL.确保安全代码,因为这些优先级可以在调用线程忙时锁定系统.(Process.PriorityClass和Thread.Priority不能很好地将优先级提升到所需的级别.)

  3. 可能通过多媒体计时器增加系统中断周期和时间更新间隔.(有各种.NET项目可以包含这些多媒体计时器功能.)

  4. 在多核系统上,核心的选择也会影响准确性.强制线程等待定时器事件在Processor0上等待是有利的.该SetThreadAffinityMask功能允许一个线程绑定到特定的CPU.(对于.Net应用程序,请参阅Thread.ProcessorAffinity.)

  5. 使用QueryPerformanceCounterQueryPerformanceFrequency作为高频时间测量的资源.(对于.Net应用程序,请参阅:创建QueryPerfCounter包装类)

  6. 确保校准性能计数器频率的值.返回的值QueryPerformanceFrequency偏离观测值偏移量和一些热漂移.这可能/将引入许多我们的错误.请参阅Windows时间戳项目以了解如何进行此类校准.

并且:是的,您可能需要进行一些硬编码.但是在Windows平台上可以观察到微秒定时非常可靠.

注意:Windows不是实时操作系统.但是Windows上的定时器非常精确.他们完全按照自己应该做的去做,并且准确度很高.关于Windows计时器及其准确性存在很多抱怨的事实是它们的行为很大程度上取决于底层硬件.这也是文档存在许多缺陷的原因.强烈建议您诊断硬件以查找各个时间服务功能.不幸的是,这导致任何程序都有一些额外的代码行与平台无关.