文章目录
方法一:System.Diagnostics.Stopwatch【相对方法二精度更高,也更稳定些】
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
{
double result = delayUs(0.005);//延时0.005ms,即5us
Console.WriteLine(result);
}
Console.ReadLine();
}
/// <summary>
/// 微秒延时
/// </summary>
/// <param name="time">延时时间,单位:ms</param>
/// <returns></returns>
public static double delayUs(double time)
{
System.Diagnostics.Stopwatch stopTime = new System.Diagnostics.Stopwatch();
stopTime.Start();
while (stopTime.Elapsed.TotalMilliseconds < time) { }
stopTime.Stop();
return stopTime.Elapsed.TotalMilliseconds;
}
}
}
运行结果:【我又测试了1000次,后边基本可以稳定在0.005(还是比较稳的)】
方法二:调用WIN API中的QueryPerformanceCounter
1、延时5us时,精度很差
using System;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Stopwatch stopTime = new System.Diagnostics.Stopwatch();
stopTime.Start();
for (int i = 0; i < 20; i++)
{
delayUs(5);//延时即5us,0.005ms
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
}
Console.WriteLine("测试结束");
Console.ReadLine();
}
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
/// <summary>
/// 微秒延时
/// </summary>
/// <param name="delay_Time">延时时间,单位:us</param>
public static void delayUs(long delay_Time)
{
long stop_Value = 0;
long start_Value = 0;
long freq = 0;
long n = 0;
QueryPerformanceFrequency(ref freq); //获取CPU频率
long count = delay_Time * freq / 1000000; //这里写成1000000就是微秒,写成1000就是毫秒
QueryPerformanceCounter(ref start_Value); //获取初始前值
while (n < count) //不能精确判定
{
QueryPerformanceCounter(ref stop_Value);//获取终止变量值
n = stop_Value - start_Value;
}
}
}
}
运行结果【延时5us时】:
2、延时500us时,精度高些
500us延时下,进一步研究:
500us延时下,分别延时1s、2s、4s、5s、10s、20s、40s、60s、120s、240s。测试源码如下:
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Stopwatch stopTime = new Stopwatch();
stopTime.Start();
//【01】总用时1s
for (int i = 0; i < 2000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【02】总用时2s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 4000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【03】总用时3s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 6000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【04】总用时4s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 8000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【05】总用时5s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 10000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【06】总用时10s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 20000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【07】总用时20s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 40000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【08】总用时40s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 80000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【09】总用时60s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 120000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
//【10】总用时120s
stopTime = new Stopwatch();
stopTime.Start();
for (int i = 0; i < 240000; i++)
{
delayUs(500);//延时即5us,0.005ms
}
Console.WriteLine(stopTime.Elapsed.TotalMilliseconds);
stopTime.Stop();
Console.WriteLine("测试结束");
Console.ReadLine();
}
[DllImport("kernel32.dll")]
extern static short QueryPerformanceCounter(ref long x);
[DllImport("kernel32.dll")]
extern static short QueryPerformanceFrequency(ref long x);
/// <summary>
/// 微秒延时
/// </summary>
/// <param name="delay_Time">延时时间,单位:us</param>
public static void delayUs(long delay_Time)
{
long stop_Value = 0;
long start_Value = 0;
long freq = 0;
long n = 0;
QueryPerformanceFrequency(ref freq); //获取CPU频率
long count = delay_Time * freq / 1000000; //这里写成1000000就是微秒,写成1000就是毫秒
QueryPerformanceCounter(ref start_Value); //获取初始前值
while (n < count) //不能精确判定
{
QueryPerformanceCounter(ref stop_Value);//获取终止变量值
n = stop_Value - start_Value;
}
}
}
}
多次运行结果如下:
对于测试结果1进行分析:
-
跑1min相差50000us,共120000个循环,每个循环(500us)相差0.417us(50000÷120000=0.417)
-
跑2min相差111000us,共240000个循环,每个循环(500us)相差0.4625us(111000÷240000=0.4625)
结论:【500us的延时,相对来说还是很准的】
方法三:DateTime.Ticks【延时效果最差】
DateTime.Ticks:表示0001 年 1 月 1 日午夜 12:00:00 以来所经历的 100 纳秒数,即Ticks的属性为100纳秒(1Ticks = 0.0001毫秒)。
//延时,单位:微妙us
public static 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;
}
while (c < t);
}