我有一个应用程序必须以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()
调用占用了大部分执行时间。就像一个注释,我不能让线程睡眠和上下文切换,因为这会导致输出速率过多的“抖动”。
关于个人资料运行的说明:
ThreadPriority.Highest
ProcessPriorityClass.High
我编写的原始程序(使用C ++)使用QueryPerformanceCounter()
和QueryPerformanceFrequency()
函数完成了相同的效果。我应该使用PInvoke而不是Stopwatch
类来使用这些调用吗?或者,还有另一种合适的方法吗?
谢谢!
答案 0 :(得分:2)
秒表位于诊断命名空间中。它不应该用于性能级别的时间。
你可能想要一个Timer。答案 1 :(得分:2)
您是否尝试过使用System.Windows.Threading.DispatcherTimer?
我用这个创建了几个程序,从来没有遇到任何延迟
答案 2 :(得分:1)
之后,进行了一些调试(受到Eric Lippert评论的启发),我意识到上面的代码完全按照要求进行。问题在于调用代码处于更高的抽象级别,这使得它的等待时间非常长。
感谢您使用System.Windows.Threading.DispatcherTimer
和System.Timers.Timer
的建议(我同时进行了投票);然而,在测试了这些中的每一个之后,它们被限制在~10毫秒的精度,这对于我的目的来说还不够好。但是,我确实发现上面的“紧密”循环代码精确到1微秒,这足以满足我当前的需求。
其他人可能会发现有用的其他资源是this CodeProject关于提高Stopwatch
准确度的文章。主要思想是从根本上降低程序承受上下文切换的可能性,从而避免浪费时间在调度队列中传播。