浅谈.NET中可用的定时器和计时器【下篇】

  上篇介绍了.net中可用的定时器,本片主要介绍.net中可用的计时器。

  • 第一种方法:使用Stopwatch

  Stopwatch 在基础计时器机制中对计时器的刻度进行计数,从而测量运行时间。如果安装的硬件和操作系统支持高分辨率性能的计数器,则 Stopwatch 类将使用该计数器来测量运行时间;否则,Stopwatch 类将使用系统计数器来测量运行时间。使用 Frequency 和 IsHighResolution 两个静态字段可以确定实现 Stopwatch 计时的精度和分辨率。

  实际上它里面就是将QueryPerformanceCounter、QueryPerformanceFrequency两个WIN API封装了一下,如果硬件支持高精度,就调用QueryPerformanceCounter,如果不支持就用DateTime.Ticks来计算。

  简单用法介绍:

using System;

using System.Diagnostics;

using System.Threading;

class Program

{

    static void Main(string[] args)

    {

        Stopwatch stopWatch = new Stopwatch();

        stopWatch.Start();

        Thread.Sleep(10000);

        stopWatch.Stop();

        // Get the elapsed time as a TimeSpan value.

        TimeSpan ts = stopWatch.Elapsed;



        // Format and display the TimeSpan value.

        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",

            ts.Hours, ts.Minutes, ts.Seconds,

            ts.Milliseconds / 10);

        Console.WriteLine("RunTime " + elapsedTime);

    }

}
  • 第二种方法:使用Environment.TickCount  

Gets the number of milliseconds elapsed since the system started.获取系统启动后经过的毫秒数。经反编译猜测它可能也是调用的GetTickCount,但是它的返回值是int,而GetTickCount与timeGetTime方法的原型中返回值是DWORD,对应C#中的uint,难道.NET对System.Environment.TickCount另外还做了什么处理么?
缺点:与GetTickCount一样,受返回值的最大位数限制。

  简答使用方法:

int aa = System.Environment.TickCount; 

Thread.Sleep(2719); 

Console.WriteLine(System.Environment.TickCount - aa); //单位毫秒
  • 第三种方法:调用WIN API中的GetTickCount
[DllImport("kernel32")]

static extern uint GetTickCount();

  从操作系统启动到现在所经过的毫秒数,精度为1毫秒,存在一定的误差。因为返回值是uint,最大值是2的32次方,因此如果服务器连续开机大约49天以后,该方法取得的返回值会归零。

  简单使用方法:

uint s1 = GetTickCount(); 

Thread.Sleep(2719); 

Console.WriteLine(GetTickCount() - s1);  //单位毫秒
  • 第四种方法:调用WIN API中的timeGetTime
[DllImport("winmm")]

static extern uint timeGetTime();

  常用于多媒体定时器中,与GetTickCount类似,也是返回操作系统启动到现在所经过的毫秒数,精度为1毫秒。一般默认的精度不止1毫秒(不同操作系统有所不同),需要调用timeBeginPeriod与timeEndPeriod来设置精度。

[DllImport("winmm")]

static extern void timeBeginPeriod(int t);

[DllImport("winmm")]

static extern void timeEndPeriod(int t);

  和GetTickCount一样,受返回值的最大位数限制。

  简单使用方法:

timeBeginPeriod(1); 

uint start = timeGetTime(); 

Thread.Sleep(2719); 

Console.WriteLine(timeGetTime() - start);  //单位毫秒 

timeEndPeriod(1); 
  • 第五种方法:Win32 API 使用QueryPerformanceCounter() QueryPerformanceFrequency() 方法支持高精度计时。

  这些方法,比“标准的”毫秒精度的计时方法如 GetTickCount() 之类有高得多的精度。另一方面来说,在 C# 中使用“非托管”的 API 函数会有一定的开销,但比起使用一点都不精确的 GetTickCount() API 函数来说要好得多了。 

  第一个函数 QueryPerformanceCounter() 查询任意时刻高精度计数器的实际值。第二个函数 QueryPerformanceFrequency() 返回高精度计数器每秒的计数值。

  然后通过将差除以每秒计数值(高精度计时器频率),就可以计算经过的时间了。duration = (stop - start) / frequency,经过时间 = (停止时间 - 开始时间) / 频率。

using System;

using System.Runtime.InteropServices;

using System.ComponentModel;

using System.Threading;



namespace Win32

{

    internal class HiPerfTimer

    {

        [DllImport("Kernel32.dll")]

        private static extern bool QueryPerformanceCounter(

            out long lpPerformanceCount);



        [DllImport("Kernel32.dll")]

        private static extern bool QueryPerformanceFrequency(

            out long lpFrequency);



        private long startTime, stopTime;

        private long freq;



        // 构造函数

        public HiPerfTimer()

        {

            startTime = 0;

            stopTime  = 0;



            if (QueryPerformanceFrequency(out freq) == false)

            {

                // 不支持高性能计数器

                throw new Win32Exception();

            }

        }



        // 开始计时器

        public void Start()

        {

            // 来让等待线程工作

            Thread.Sleep(0);



            QueryPerformanceCounter(out startTime);

        }



        // 停止计时器

        public void Stop()

        {

            QueryPerformanceCounter(out stopTime);

        }



        // 返回计时器经过时间(单位:秒)

        public double Duration

        {

            get

            {

                return (double)(stopTime - startTime) / (double) freq;

            }

        }

    }

}

  使用这个类很简单。只需要创建一个 HiPerfTimer 的实例,然后调用 Start() 开始计时,Stop() 停止计时。要获得经过的时间,调用 Duration() 函数即可。

HiPerfTimer pt = new HiPerfTimer();// 创建新的 HiPerfTimer 对象

pt.Start();  // 启动计时器

Console.WriteLine("Test\n");// 需要计时的代码

pt.Stop();// 停止计时器

Console.WriteLine("Duration: {0} sec\n", pt.Duration); // 打印需要计时部分代码的用时

 

  还有其他的一些方法,譬如cpu的时间戳计时等。

  就总结这么多,希望对你有帮助~

你可能感兴趣的:(.net)