C#怎么C# 延迟 函数1微秒

windows下实现微秒级的延时
1.微秒级的延时肯定不能基于消息(SetTimer函数),因为一出现消息堵塞等就会影响精
度,而且setTimer单位才是毫秒.实际响应时间可能要到55毫秒左右.
2.微秒级的延时也不能不能基于中断,VxD最快的时钟服务程序Set_Global_Time_Out函数
才能保证1毫秒的精度.其他挂接int 8H中断处理函数等,只能保证55ms的精度.(有时还不
3.因此可以想到汇编下的那种基于循环执行语句的那种延时.但汇编那种代码不通用,跟
cpu的频率有关.
所以可以用windows下的几个函数来写出通用代
码.GetTickCout,timeGetTime,QueryPerformanceCounter.
1)GetTickCout响应只能保证55ms的精度
2)timeGetTime只能保证1ms的精度
3)而QueryPerformanceCounter函数不依赖计算中断的次数,而是靠读取别的硬件时钟来
实现的,可以有0.8微秒的精度.这个系统不支持windows 95以下的系统,不过这些系统应
该没人用了吧.呵呵.
下面是示例代码:
//LARGE_INTEGER类型类似一个64位的整型,是一个union,里面是LongLong类型和两个
long组成的结构体的union.
//QueryPerformanceFrequency函数得到你的计算机里高精度计时器每秒计时多少次,
//参数LARGE_INTEGER,返回false表示你的当前计算机硬件不支持高精度计时器.
//QueryPerformanceCounter函数得到当前计时器记了多少次.类似与GetTickCout.
#include &windows.h&
#include &iostream&
void main(){
int delayTime = 20; //微秒级的延时.
LARGE_INTEGER m_liPerfFreq={0};
if (!QueryPerformanceFrequency(&m_liPerfFreq))
cout &&"你的当前计算机硬件不支持高精度计时器"&&
LARGE_INTEGER m_liPerfStart={0};
QueryPerformanceCounter(&m_liPerfStart);
LARGE_INTEGER liPerfNow={0};
QueryPerformanceCounter(&liPerfNow);
double time=( ((liPerfNow.QuadPart -
m_liPerfStart.QuadPart)*1000000)/(double)m_liPerfFreq.QuadPart);
if (time &= delayTime)
cout.precision(40);
cout && "开始" &&(double)m_liPerfStart.QuadPart &&
cout && "结束" &&(double)liPerfNow.QuadPart &&
cout&&"时间精度"&&(1/(double)m_liPerfFreq.QuadPart)*1000000&&"微秒"&&
cout && "延时" &&( ((liPerfNow.QuadPart - m_liPerfStart.QuadPart)
*1000000)/(double)m_liPerfFreq.QuadPart)&&"微秒"&&
因为windows是多任务系统,只要保证windows执行这段代码时不被其他进程打断,就可以
保证延时微秒级成功.出现打断的几率很小.一般可以不考虑.如果代码执行时间低于一
个时间片,那就100%不会被打断了.
在SDK中,可以用DWORD timeGetTime(VOID)函数获取系统时间,其返回值是毫秒单位的。可以用其实现延时功能的函数。
void Delay(DWORD delayTime)
DWORD delayTimeB
DWORD delayTimeE
delayTimeBegin=timeGetTime();
delayTimeEnd=timeGetTime();
}while(delayTimeEnd-delayTimeBegin&delayTime)
在使用timeGetTime之前应先包含头文件#i nclude &Mmsystem.h&或#i nclude
&Windows.h&并在project-&settings-&link-&Object/library
modules中添加winmm.lib
也可以在文件头部添加 #pragma comment( lib,"winmm.lib" )
命令行:#pragma comment( lib,"xxx.lib" )时预编译处理指令,让vc将winmm.lib添加到工程中去进行编译。
在Windows平台下,常用的计时器有两种,一种是timeGetTime多媒体计时器,它可以提供毫秒级的计时。但这个精度对很多应用场合而言
还是太粗糙了。另一种是QueryPerformanceCount计数器,随系统的不同可以提供微秒级的计数。对于实时图形处理、多媒体数据流处理、或
者实时系统构造的程序员,善用QueryPerformanceCount/QueryPerformanceFrequency是一项基本功。
  本文要介绍的,是另一种直接利用Pentium
CPU内部时间戳进行计时的高精度计时手段。以下讨论主要得益于《Windows图形编程》一书,第15页-17页,有兴趣的读者可以直接参考该书。关于
RDTSC指令的详细讨论,可以参考Intel产品手册。本文仅仅作抛砖之用。
  在Intel
Pentium以上级别的CPU中,有一个称为“时间戳(Time
Stamp)”的部件,它以64位无符号整型数的格式,记录了自CPU上电以来所经过的时钟周期数。由于目前的CPU主频都非常高,因此这个部件可以达到
纳秒级的计时精度。这个精确性是上述两种方法所无法比拟的。
  在Pentium以上的CPU中,提供了一条机器指令RDTSC(Read Time Stamp
Counter)来读取这个时间戳的数字,并将其保存在EDX:EAX寄存器对中。由于EDX:EAX寄存器对恰好是Win32平台下C++语言保存函数
返回值的寄存器,所以我们可以把这条指令看成是一个普通的函数调用。像这样:
inline unsigned __int64 GetCycleCount()
__asm RDTSC
但是不行,因为RDTSC不被C++的内嵌汇编器直接支持,所以我们要用_emit伪指令直接嵌入该指令的机器码形式0X0F、0X31,如下:
inline unsigned __int64 GetCycleCount()
__asm _emit 0x0F
__asm _emit 0x31
以后在需要计数器的场合,可以像使用普通的Win32 API一样,调用两次GetCycleCount函数,比较两个返回值的差,像这样:
t = (unsigned long)GetCycleCount();
//Do Something time-intensive ...
t -= (unsigned long)GetCycleCount();
  《Windows图形编程》第15页编写了一个类,把这个计数器封装起来。有兴趣的读者可以去参考那个类的代码。作者为了更精确的定时,做了一
点小小的改进,把执行RDTSC指令的时间,通过连续两次调用GetCycleCount函数计算出来并保存了起来,以后每次计时结束后,都从实际得到的
计数中减掉这一小段时间,以得到更准确的计时数字。但我个人觉得这一点点改进意义不大。在我的机器上实测,这条指令大概花掉了几十到100多个周期,在
800MHz的机器上,这不过是十分之一微秒的时间。对大多数应用来说,这点时间完全可以忽略不计;而对那些确实要精确到纳秒数量级的应用来说,这个补偿
也过于粗糙了。
这个方法的优点是:
1.高精度。可以直接达到纳秒级的计时精度(在1GHz的CPU上每个时钟周期就是一纳秒),这是其他计时方法所难以企及的。
2.成本低。timeGetTime 函数需要链接多媒体库winmm.lib,QueryPerformance*
函数根据MSDN的说明,需要硬件的支持(虽然我还没有见过不支持的机器)和KERNEL库的支持,所以二者都只能在Windows平台下使用(关于
DOS平台下的高精度计时问题,可以参考《图形程序开发人员指南》,里面有关于控制定时器8253的详细说明)。但RDTSC指令是一条CPU指令,凡是
i386平台下Pentium以上的机器均支持,甚至没有平台的限制(我相信i386版本UNIX和Linux下这个方法同样适用,但没有条件试验),而
且函数调用的开销是最小的。
3.具有和CPU主频直接对应的速率关系。一个计数相当于1/(CPU主频Hz数)秒,这样只要知道了CPU的主频,可以直接计算出时间。这和
QueryPerformanceCount不同,后者需要通过QueryPerformanceFrequency获取当前计数器每秒的计数次数才能换
算成时间。
这个方法的缺点是:
1.现有的C/C++编译器多数不直接支持使用RDTSC指令,需要用直接嵌入机器码的方式编程,比较麻烦。
2.数据抖动比较厉害。其实对任何计量手段而言,精度和稳定性永远是一对矛盾。如果用低精度的timeGetTime来计时,基本上每次计时的结果都是相同的;而RDTSC指令每次结果都不一样,经常有几百甚至上千的差距。这是这种方法高精度本身固有的矛盾。
关于这个方法计时的最大长度,我们可以简单的用下列公式计算:
自CPU上电以来的秒数 = RDTSC读出的周期数 / CPU主频速率(Hz)
64位无符号整数所能表达的最大数字是1.8×10^19,在我的Celeron 800上可以计时大约700年(书中说可以在200MHz的Pentium上计时117年,这个数字不知道是怎么得出来的,与我的计算有出入)。无论如何,我们大可不必关心溢出的问题。
下面是几个小例子,简要比较了三种计时方法的用法与精度
//Timer1.cpp 使用了RDTSC指令的Timer类//KTimer类的定义可以参见《Windows图形编程》P15
//编译行:CL Timer1.cpp /link USER32.lib
#include &stdio.h&
#include "KTimer.h"
timer.Start();
Sleep(1000);
t = timer.Stop();
printf("Lasting Time: %d/n",t);
//Timer2.cpp 使用了timeGetTime函数
//需包含&mmsys.h&,但由于Windows头文件错综复杂的关系
//简单包含&windows.h&比较偷懒:)
//编译行:CL timer2.cpp /link winmm.lib
#include &windows.h&
#include &stdio.h&
DWORD t1, t2;
t1 = timeGetTime();
Sleep(1000);
t2 = timeGetTime();
printf("Begin Time: %u/n", t1);
printf("End Time: %u/n", t2);
printf("Lasting Time: %u/n",(t2-t1));
//Timer3.cpp 使用了QueryPerformanceCounter函数
//编译行:CL timer3.cpp /link KERNEl32.lib
#include &windows.h&
#include &stdio.h&
LARGE_INTEGER t1, t2,
QueryPerformanceFrequency(&tc);
printf("Frequency: %u/n", tc.QuadPart);
QueryPerformanceCounter(&t1);
Sleep(1000);
QueryPerformanceCounter(&t2);
printf("Begin Time: %u/n", t1.QuadPart);
printf("End Time: %u/n", t2.QuadPart);
printf("Lasting Time: %u/n",( t2.QuadPart- t1.QuadPart));
////////////////////////////////////////////////
//以上三个示例程序都是测试1秒钟休眠所耗费的时间
file://测/试环境:Celeron 800MHz / 256M SDRAM
// Windows 2000 Professional SP2
// Microsoft Visual C++ 6.0 SP5
////////////////////////////////////////////////
以下是Timer1的运行结果,使用的是高精度的RDTSC指令
Lasting Time:
以下是Timer2的运行结果,使用的是最粗糙的timeGetTime API
Begin Time:
Lasting Time: 1001
以下是Timer3的运行结果,使用的是QueryPerformanceCount API
Frequency: 3579545
Begin Time:
Lasting Time: 3569712
http://blog.csdn.net/lhsxsh/archive//4151393.aspx
没有更多推荐了,C# 怎么实现精确延时
[问题点数:40分,结帖人ares1986]
本版专家分:245
结帖率 100%
CSDN今日推荐
本版专家分:245
本版专家分:635
本版专家分:371
本版专家分:245
本版专家分:449646
2017年 总版技术专家分年内排行榜第十2013年 总版技术专家分年内排行榜第八
2017年2月 总版技术专家分月排行榜第三
2018年6月 .NET技术大版内专家分月排行榜第一2018年1月 .NET技术大版内专家分月排行榜第一2017年5月 .NET技术大版内专家分月排行榜第一2017年4月 .NET技术大版内专家分月排行榜第一2017年3月 .NET技术大版内专家分月排行榜第一2017年2月 .NET技术大版内专家分月排行榜第一2016年10月 .NET技术大版内专家分月排行榜第一2016年8月 .NET技术大版内专家分月排行榜第一2016年7月 .NET技术大版内专家分月排行榜第一
2018年4月 .NET技术大版内专家分月排行榜第二2018年3月 .NET技术大版内专家分月排行榜第二2017年12月 .NET技术大版内专家分月排行榜第二2017年9月 .NET技术大版内专家分月排行榜第二2017年7月 .NET技术大版内专家分月排行榜第二2017年6月 .NET技术大版内专家分月排行榜第二2016年12月 .NET技术大版内专家分月排行榜第二2016年9月 .NET技术大版内专家分月排行榜第二2016年6月 .NET技术大版内专家分月排行榜第二2016年3月 .NET技术大版内专家分月排行榜第二2016年1月 .NET技术大版内专家分月排行榜第二2015年12月 .NET技术大版内专家分月排行榜第二2015年2月 .NET技术大版内专家分月排行榜第二2015年1月 .NET技术大版内专家分月排行榜第二2014年11月 .NET技术大版内专家分月排行榜第二2014年5月 .NET技术大版内专家分月排行榜第二2014年4月 .NET技术大版内专家分月排行榜第二2012年2月 多媒体/设计/Flash/Silverlight 开发大版内专家分月排行榜第二
本版专家分:4887
本版专家分:398083
2014年 荣获名人称号2013年 荣获名人称号2012年 荣获名人称号
2013年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第四
本版专家分:3835
本版专家分:966
本版专家分:1228
本版专家分:7035
本版专家分:4887
本版专家分:966
本版专家分:18541
本版专家分:4887
本版专家分:966
本版专家分:4887
本版专家分:1495
本版专家分:2889
本版专家分:287
本版专家分:287
本版专家分:6147
本版专家分:966
本版专家分:4887
本版专家分:4887
本版专家分:4887
本版专家分:2889
本版专家分:4887
本版专家分:4887
匿名用户不能发表回复!|
其他相关推荐如何得到1毫秒级的延时精度
[问题点数:100分,结帖人wangxiangsjz]
本版专家分:3831
结帖率 100%
CSDN今日推荐
本版专家分:10044
本版专家分:45
本版专家分:7743
本版专家分:18349
2003年6月 C++ Builder大版内专家分月排行榜第一
2003年5月 C++ Builder大版内专家分月排行榜第二
2003年4月 C++ Builder大版内专家分月排行榜第三
本版专家分:3010
本版专家分:10044
本版专家分:5669
本版专家分:1708
本版专家分:9174
本版专家分:24856
本版专家分:489
本版专家分:3831
匿名用户不能发表回复!|
其他相关推荐C#怎么延迟1微秒_百度知道
C#怎么延迟1微秒
我有更好的答案
一般电脑做不到,C#对时间片的管理也没做到这个级别
thread.sleep(1);
需要thread 类
System.Threading.Thread.Sleep(1);
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。}

我要回帖

更多关于 有什么程序可以延迟在微秒计算 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信