• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
wysky
博客园    首页    新随笔    联系   管理    订阅  订阅
准确计算时间差
简单地使用 beginDate - endDate 不精确,总是某个值的倍数,比如 0.015625 秒的倍数,值比较小时,干脆就是个0 (0 倍)。 .NET Framework v2.0 中新增了一个 System.Diagnostics.Stopwatch 对象,用法也相当简单,那么在v1.1下面如何实现呢,见代码~
简单地使用 beginDate - endDate 不精确,总是某个值的倍数,比如 0.015625 秒的倍数,值比较小时,干脆就是个0 (0 倍)。

.NET Framework v2.0 中新增了一个 System.Diagnostics.Stopwatch 对象,本文就是说用它来计算时间差,.NET 2.0 中是现成的,因此对 2.0 来说,这文章没什么意义,只要知道有这个对象就可以了,用法也相当简单,举例:
public void SomeMethod()
{
    Stopwatch stopwatch 
= Stopwatch.StartNew();
    
// do something 
    
// 仅仅简单举例, Stopwatch 还提供了其他更为详细的属性和方法。
    Console.WriteLine("Elapsed Seconds: {0}", stopwatch.Elapsed.TotalSeconds);
}

在 1.1 里没有提供,但只需把该对象完整的反编译代码 Copy 出来自建一个 Stopwatch 对象,再做一点小改动就 OK 了。 代码与举例:
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;

namespace Zealot.Framework.Web.Utils
{
    
/// <summary>
    
/// v1.1 没有 Stopwatch,从 v2.0 复制出来
    
/// </summary>
    public class Stopwatch
    {
        
// Fields
        private long elapsed;
        
public static readonly long Frequency;
        
public static readonly bool IsHighResolution;
        
private bool isRunning;
        
private long startTimeStamp;
        
private static readonly double tickFrequency;
        
private const long TicksPerMillisecond = 0x2710;
        
private const long TicksPerSecond = 0x989680;

        
// Methods
        static Stopwatch()
        {
            
if (!SafeNativeMethods.QueryPerformanceFrequency(out Frequency))
            {
                IsHighResolution 
= false;
                Frequency 
= 0x989680;
                tickFrequency 
= 1;
            }
            
else
            {
                IsHighResolution 
= true;
                tickFrequency 
= 10000000;
                tickFrequency 
/= (double)Frequency;
            }
        }

        
public Stopwatch()
        {
            
this.Reset();
        }

        
private long GetElapsedDateTimeTicks()
        {
            
long rawElapsedTicks = this.GetRawElapsedTicks();
            
if (IsHighResolution)
            {
                
double num2 = rawElapsedTicks;
                num2 
*= tickFrequency;
                
return (long)num2;
            }
            
return rawElapsedTicks;
        }

        
private long GetRawElapsedTicks()
        {
            
long elapsed = this.elapsed;
            
if (this.isRunning)
            {
                
long num3 = GetTimestamp() - this.startTimeStamp;
                elapsed 
+= num3;
            }
            
return elapsed;
        }

        
public static long GetTimestamp()
        {
            
if (IsHighResolution)
            {
                
long num = 0;
                SafeNativeMethods.QueryPerformanceCounter(
out num);
                
return num;
            }
            
return DateTime.UtcNow.Ticks;
        }

        
public void Reset()
        {
            
this.elapsed = 0;
            
this.isRunning = false;
            
this.startTimeStamp = 0;
        }

        
public void Start()
        {
            
if (!this.isRunning)
            {
                
this.startTimeStamp = GetTimestamp();
                
this.isRunning = true;
            }
        }

        
public static Stopwatch StartNew()
        {
            Stopwatch stopwatch 
= new Stopwatch();
            stopwatch.Start();
            
return stopwatch;
        }

        
public void Stop()
        {
            
if (this.isRunning)
            {
                
long num2 = GetTimestamp() - this.startTimeStamp;
                
this.elapsed += num2;
                
this.isRunning = false;
            }
        }

        
// Properties
        public TimeSpan Elapsed
        {
            
get
            {
                
return new TimeSpan(this.GetElapsedDateTimeTicks());
            }
        }

        
public long ElapsedMilliseconds
        {
            
get
            {
                
return (this.GetElapsedDateTimeTicks() / ((long)0x2710));
            }
        }

        
public long ElapsedTicks
        {
            
get
            {
                
return this.GetRawElapsedTicks();
            }
        }

        
public bool IsRunning
        {
            
get
            {
                
return this.isRunning;
            }
        }
    }
}

编译时发现有 2 处错误,无法找到 SafeNativeMethods 对象,因为它是 internal 访问限制的。 而 在这个类里用到了 SafeNativeMethods 中的两个方法,QueryPerformanceFrequency 和 QueryPerformanceCounter,把他们也反编译出来,直接加入自建的 Stopwatch 类当中,或者在与 Stopwatch 相同的命名空间下同样自建一个 SafeNativeMethods 类就可以了。
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;

namespace Zealot.Framework.Web.Utils
{
    [SuppressUnmanagedCodeSecurity]
    
internal class SafeNativeMethods
    {
        [DllImport(
"kernel32.dll")]
        
internal static extern bool QueryPerformanceCounter(out long value);

        [DllImport(
"kernel32.dll")]
        
internal static extern bool QueryPerformanceFrequency(out long value);
    }
}
转自:http://www.zealotforce.net/reply-638.aspx
posted on 2007-12-06 19:23  文's sky  阅读(492)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3