Windows不是实时操作系统,小于系统时间片调度的延迟没有意义,就算实时操作系统,你也得考虑总线、内存、IO的延迟了。给你的建议就是根本不要延迟,你就和你的客户说延迟了,他们自己想办法验证是不是延迟了1微秒。顺便说下,1us=0.000001s,也就是一个2GHz CPU 2000个时钟周期。理论上来说,你找一个1时钟周期执行1次的指令(比如nop)执行2000次就可以了。
lz把“需求”翻译为Thread.Sleep,这根本就应该退回给需求去了!
刚查查msdn,C# 还是提供了类似的参数机制来调用的,不过就准确度而言,惨不忍睹。 public static void SleepTest() { int count = 1000; SleepTest(count, 10); SleepTest(count, 1000); } private static void SleepTest(int count, long ticks) { TimeSpan ts = new TimeSpan(ticks); long m_startTime = Stopwatch.GetTimestamp(); for (int i = 0; i < count; i++) { System.Threading.Thread.Sleep(ts); //System.Threading.Thread.Sleep(1); } Console.WriteLine("Run {0} times for {1} seconds.", count, (Stopwatch.GetTimestamp() - m_startTime) / (double)Stopwatch.Frequency); }在我机器上,上面2个的时间差不多; 可如果用 SleepTest(count, 10000); 就要15多秒,和用 Sleep(1) 差不多。
#region 延时函数 精确到1微秒 private void delay(long t) { long b = DateTime.Now.Ticks / 10; long e = 0; long c = 0; ; do { e = DateTime.Now.Ticks / 10; c = e - b; Application.DoEvents(); } while (c < t); }
试试Stopwatch,它的内部实现调用是QueryPerformanceCounter long frequency = Stopwatch.Frequency / 1000000; Stopwatch time = new Stopwatch(); time.Start(); while (time.ElapsedTicks < frequency) ;
当然你也可以直接调用Stopwatch.GetTimestamp long frequency = Stopwatch.Frequency / 1000000; long endTime = frequency + Stopwatch.GetTimestamp(); while (Stopwatch.GetTimestamp() < endTime) ;
{
int count = 1000;
SleepTest(count, 10);
SleepTest(count, 1000);
} private static void SleepTest(int count, long ticks)
{
TimeSpan ts = new TimeSpan(ticks);
long m_startTime = Stopwatch.GetTimestamp();
for (int i = 0; i < count; i++)
{
System.Threading.Thread.Sleep(ts);
//System.Threading.Thread.Sleep(1);
} Console.WriteLine("Run {0} times for {1} seconds.", count, (Stopwatch.GetTimestamp() - m_startTime) / (double)Stopwatch.Frequency);
}在我机器上,上面2个的时间差不多;
可如果用 SleepTest(count, 10000);
就要15多秒,和用 Sleep(1) 差不多。
Spin 就是空操作. 像API, BOOL WINAPI InitializeCriticalSectionAndSpinCount各种,轻量级的 同步,包括 .net的 ReaderWriterLock, 都有 Spin
具体,要等待几个iterations? 那么, 把处理器频率,和 等待的微秒数,换算下
Sleep什么的,进程/线程,切换出去运行状态, 就不可靠了.汇编里面的, NOP,就是用来 精确延时的.Net,用Thread.SpinWait的时候,需要把 进程/线程,优先级,调到最高.这样,能 比较,[近似地],符合要求.
但是,仍然不能确保精确. 毕竟呢,这个是多道程序系统,进程三状态,不能持续保持在Running状态
工业上毫秒级就算高精度了,不知道精度这么高有啥用。如果是特殊用途就需要特殊硬件,而不是随便说需求这样……需求不合理上帝也没办法啊。
你既然不懂硬件,那么就试试,我建议你就延迟1ms,虽然这根本是脱裤子放屁,但人问起来你至少能说你做了,而且运行起来毫无鸭梨。。
private void delay(long t)
{
long b = DateTime.Now.Ticks / 10;
long e = 0; long c = 0; ;
do
{
e = DateTime.Now.Ticks / 10;
c = e - b;
Application.DoEvents();
}
while (c < t);
}
普通程序能到毫秒级就顶天了。
long frequency = Stopwatch.Frequency / 1000000;
Stopwatch time = new Stopwatch();
time.Start();
while (time.ElapsedTicks < frequency) ;
long frequency = Stopwatch.Frequency / 1000000;
long endTime = frequency + Stopwatch.GetTimestamp();
while (Stopwatch.GetTimestamp() < endTime) ;
正常情况下,正确使用Frequency不超过0.3微妙,上下浮动不超过0.15微妙
{
_LARGE_INTEGER t1, t2;
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
QueryPerformanceCounter(&t1);
int tk = GetTickCount();
do
{
QueryPerformanceCounter(&t2);
} while( ((t2.QuadPart-t1.QuadPart)*(1000LL*1000LL*1000LL)/freq.QuadPart) < 1000LL*us);
}
KeDelayExecutionThread是什么,不懂,没用过
你就写成这样,让需求的人测试去吧
发现这么多人从C#不能延迟1微秒说到不能延迟1ms到windows操作系统最大精度只能是10ms,我真服了,你们说的只是C里面的那个sleep函数而已,它的精度大概是15ms,而C#里面的Thread.Sleep(1)绝对是标准1ms,不信的你们可以自己测试,可以用Stopwatch计时,如果认为系统计时不准,那么你可以拿个秒表计时,看看一千次循环,每次执行Thread.Sleep(1)是不是正好1秒,还是某些人说的最低精度10ms,那么就是10秒,我想一切以事实说话,绝对是1秒。还有,说windows的最大精度10ms的,KeDelayExecutionThread用过没,先不说它的精度如何,最起码1ms是没有任何问题的,如果最最基础的内核延迟函数都没用过就说windows系统不行是不是太过草率了。。