• 浅谈.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的时间戳计时等。

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

  • 相关阅读:
    HDU 1224 无环有向最长路
    HDU 1220 简单数学题
    HDU 1203 背包问题
    HDU 1176 DP
    HDU 1159 LCS最长公共子序列
    HDU 1160 排序或者通过最短路两种方法解决
    hdu 2349 最小生成树
    次小生成树的学习
    最小生成树prime算法模板
    poj 1679 判断最小生成树是否唯一
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/2623731.html
Copyright © 2020-2023  润新知