重复调用时,System.Diagnostics.Stopwatch类通常会变慢吗?

时间:2012-02-16 20:51:43

标签: c# performance timer stopwatch

我有一个应用程序必须以33ms +/-几毫秒的固定间隔发送数据包。

所以,我想出了一个SpinTimer类,如下所示:

class SpinTimer
{
    public void SpinWait(double waitTimeInSeconds)
    {
        if (waitTimeInSeconds < 0.0)
        {
            throw new ArgumentOutOfRangeException("waitTimeInSeconds", "Must be >= 0.0");
        }

        Stopwatch timer = new Stopwatch();
        double elapsed = 0.0;
        timer.Start();
        do
        {
            elapsed = (double)timer.ElapsedTicks / (double)Stopwatch.Frequency;
        } while (elapsed < waitTimeInSeconds);
    }
}

但是,在对代码进行概要分析后,我发现System.Diagnostics.Stopwatch.GetTimestamp()调用占用了大部分执行时间。就像一个注释,我不能让线程睡眠和上下文切换,因为这会导致输出速率过多的“抖动”。

关于个人资料运行的说明:

  1. 主题优先级设置为ThreadPriority.Highest
  2. 流程优先级设置为ProcessPriorityClass.High
  3. 我编写的原始程序(使用C ++)使用QueryPerformanceCounter()QueryPerformanceFrequency()函数完成了相同的效果。我应该使用PInvoke而不是Stopwatch类来使用这些调用吗?或者,还有另一种合适的方法吗?

    谢谢!

3 个答案:

答案 0 :(得分:2)

秒表位于诊断命名空间中。它不应该用于性能级别的时间。

你可能想要一个Timer。

答案 1 :(得分:2)

您是否尝试过使用System.Windows.Threading.DispatcherTimer?

我用这个创建了几个程序,从来没有遇到任何延迟

答案 2 :(得分:1)

之后,进行了一些调试(受到Eric Lippert评论的启发),我意识到上面的代码完全按照要求进行。问题在于调用代码处于更高的抽象级别,这使得它的等待时间非常长。

感谢您使用System.Windows.Threading.DispatcherTimerSystem.Timers.Timer的建议(我同时进行了投票);然而,在测试了这些中的每一个之后,它们被限制在~10毫秒的精度,这对于我的目的来说还不够好。但是,我确实发现上面的“紧密”循环代码精确到1微秒,这足以满足我当前的需求。

其他人可能会发现有用的其他资源是this CodeProject关于提高Stopwatch准确度的文章。主要思想是从根本上降低程序承受上下文切换的可能性,从而避免浪费时间在调度队列中传播。